diff --git a/common/primitives/core/Cargo.toml b/common/primitives/core/Cargo.toml index 0734ba84c8..c07ca703d3 100644 --- a/common/primitives/core/Cargo.toml +++ b/common/primitives/core/Cargo.toml @@ -7,18 +7,18 @@ version = '0.1.0' [dependencies] base58 = { version = "0.2", default-features = false } base64 = { version = "0.13", default-features = false, features = ["alloc"] } -parity-scale-codec = { version = "3.6", default-features = false, features = ["derive", "max-encoded-len"] } -strum = { version = "0.26", default-features = false } -strum_macros = { version = "0.26", default-features = false } -serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } -serde_json = { version = "=1.0.120", default-features = false } +chrono = { version = "0.4", default-features = false, features = ["serde"] } der = { version = "0.6.0", default-features = false } hex = { version = "0.4", default-features = false } hex-literal = { version = "0.4.1", default-features = false } -chrono = { version = "0.4", default-features = false, features = ["serde"] } +parity-scale-codec = { version = "3.6", default-features = false, features = ["derive", "max-encoded-len"] } ring = { version = "0.16.20", default-features = false, features = ["alloc"] } -x509-cert = { version = "0.1.0", default-features = false, features = ["alloc"] } +serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } +serde_json = { version = "=1.0.120", default-features = false } +strum = { version = "0.26", default-features = false } +strum_macros = { version = "0.26", default-features = false } webpki = { version = "=0.102.0-alpha.3", git = "https://github.com/rustls/webpki", rev = "da923ed", package = "rustls-webpki", default-features = false, features = ["alloc", "ring"] } +x509-cert = { version = "0.1.0", default-features = false, features = ["alloc"] } frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.1.0", default-features = false } pallet-evm = { git = "https://github.com/paritytech/frontier", branch = "polkadot-v1.1.0", default-features = false } diff --git a/common/primitives/core/src/lib.rs b/common/primitives/core/src/lib.rs index 647280f5c2..a04fdf9844 100644 --- a/common/primitives/core/src/lib.rs +++ b/common/primitives/core/src/lib.rs @@ -32,9 +32,11 @@ pub use assertion::Assertion; pub mod identity; pub use identity::*; -mod omni_account; +pub mod omni_account; pub use omni_account::*; +extern crate alloc; +extern crate core; use alloc::{format, str, str::FromStr, string::String, vec, vec::Vec}; use sp_runtime::{traits::ConstU32, BoundedVec}; diff --git a/common/primitives/core/src/teebag/sgx_verify/mod.rs b/common/primitives/core/src/teebag/sgx_verify/mod.rs index d07583dc14..2a8ee2d251 100644 --- a/common/primitives/core/src/teebag/sgx_verify/mod.rs +++ b/common/primitives/core/src/teebag/sgx_verify/mod.rs @@ -28,8 +28,6 @@ //! //! * https://download.01.org/intel-sgx/linux-1.5/docs/Intel_SGX_Developer_Guide.pdf -pub extern crate alloc; - use self::{ collateral::{EnclaveIdentity, TcbInfo}, netscape_comment::NetscapeComment, diff --git a/parachain/Cargo.lock b/parachain/Cargo.lock index a83af27e12..6a4230119a 100644 --- a/parachain/Cargo.lock +++ b/parachain/Cargo.lock @@ -7831,7 +7831,6 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-core", - "sp-core-hashing", "sp-io", "sp-keyring", "sp-runtime", diff --git a/parachain/pallets/omni-account/Cargo.toml b/parachain/pallets/omni-account/Cargo.toml index 451bb0ee7e..fb5c35df7e 100644 --- a/parachain/pallets/omni-account/Cargo.toml +++ b/parachain/pallets/omni-account/Cargo.toml @@ -13,7 +13,7 @@ scale-info = { workspace = true } frame-support = { workspace = true } frame-system = { workspace = true } sp-core = { workspace = true } -sp-core-hashing = { workspace = true } + sp-io = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index b4482f579f..ff5fab9d0f 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -3529,6 +3529,7 @@ dependencies = [ "itp-ocall-api", "itp-sgx-crypto", "itp-sgx-externalities", + "itp-sgx-io", "itp-stf-interface", "itp-stf-primitives", "itp-stf-state-handler", @@ -4314,6 +4315,7 @@ dependencies = [ "frame-support", "hash-db 0.15.2", "itp-types", + "litentry-hex-utils", "parity-scale-codec", "sgx_tstd", "sp-core", @@ -5221,6 +5223,21 @@ dependencies = [ "sgx_tstd", ] +[[package]] +name = "lc-omni-account" +version = "0.1.0" +dependencies = [ + "frame-support", + "itp-ocall-api", + "itp-storage", + "itp-types", + "lazy_static", + "litentry-primitives", + "log 0.4.20", + "sgx_tstd", + "sp-core", +] + [[package]] name = "lc-parachain-extrinsic-task-receiver" version = "0.1.0" diff --git a/tee-worker/Cargo.toml b/tee-worker/Cargo.toml index 324f8dc8f5..64d89bec74 100644 --- a/tee-worker/Cargo.toml +++ b/tee-worker/Cargo.toml @@ -56,6 +56,7 @@ members = [ "identity/litentry/core/native-task/sender", "identity/litentry/core/native-task/receiver", "identity/litentry/core/identity-verification", + "identity/litentry/core/omni-account", "identity/litentry/core/stf-task/sender", "identity/litentry/core/stf-task/receiver", "identity/litentry/core/service", @@ -300,6 +301,7 @@ lc-stf-task-sender = { path = "identity/litentry/core/stf-task/sender", default- lc-stf-task-receiver = { path = "identity/litentry/core/stf-task/receiver", default-features = false } lc-vc-task-sender = { path = "identity/litentry/core/vc-task/sender", default-features = false } lc-vc-task-receiver = { path = "identity/litentry/core/vc-task/receiver", default-features = false } +lc-omni-account = { path = "identity/app-libs/omni-account", default-features = false } lc-native-task-sender = { path = "identity/litentry/core/native-task/sender", default-features = false } lc-native-task-receiver = { path = "identity/litentry/core/native-task/receiver", default-features = false } diff --git a/tee-worker/bitacross/enclave-runtime/Cargo.lock b/tee-worker/bitacross/enclave-runtime/Cargo.lock index 7c196c4cd8..c6e9aa1a46 100644 --- a/tee-worker/bitacross/enclave-runtime/Cargo.lock +++ b/tee-worker/bitacross/enclave-runtime/Cargo.lock @@ -988,6 +988,7 @@ dependencies = [ "serde 1.0.204", "serde_json 1.0.120", "sp-core", + "sp-core-hashing", "sp-io", "sp-runtime", "sp-std", @@ -2556,6 +2557,7 @@ dependencies = [ "frame-support", "hash-db 0.15.2", "itp-types", + "litentry-hex-utils 0.1.0", "parity-scale-codec", "sgx_tstd", "sp-core", diff --git a/tee-worker/bitacross/enclave-runtime/src/ocall/on_chain_ocall.rs b/tee-worker/bitacross/enclave-runtime/src/ocall/on_chain_ocall.rs index e80c1fb112..124f7fabd9 100644 --- a/tee-worker/bitacross/enclave-runtime/src/ocall/on_chain_ocall.rs +++ b/tee-worker/bitacross/enclave-runtime/src/ocall/on_chain_ocall.rs @@ -125,9 +125,13 @@ impl EnclaveOnChainOCallApi for OcallApi { Ok(storage_entries) } - fn get_storage_keys(&self, key_prefix: Vec) -> Result>> { - // always using the latest state - we need to support optional header - let requests = vec![WorkerRequest::ChainStorageKeys(key_prefix, None)]; + fn get_storage_keys>( + &self, + key_prefix: Vec, + header: Option<&H>, + ) -> Result>> { + let header_hash = header.map(|h| h.hash()); + let requests = vec![WorkerRequest::ChainStorageKeys(key_prefix, header_hash)]; let responses: Vec>> = self .worker_request::>(requests, &ParentchainId::Litentry)? diff --git a/tee-worker/common/core-primitives/ocall-api/src/lib.rs b/tee-worker/common/core-primitives/ocall-api/src/lib.rs index d4a0a9b944..ca5090e88c 100644 --- a/tee-worker/common/core-primitives/ocall-api/src/lib.rs +++ b/tee-worker/common/core-primitives/ocall-api/src/lib.rs @@ -118,7 +118,11 @@ pub trait EnclaveOnChainOCallApi: Clone + Send + Sync { // Litentry // given a key prefix, get all storage keys - fn get_storage_keys(&self, key_prefix: Vec) -> Result>>; + fn get_storage_keys>( + &self, + key_prefix: Vec, + header: Option<&H>, + ) -> Result>>; } /// Trait for sending metric updates. diff --git a/tee-worker/common/core-primitives/storage/Cargo.toml b/tee-worker/common/core-primitives/storage/Cargo.toml index d3c48d6e05..72659e1b52 100644 --- a/tee-worker/common/core-primitives/storage/Cargo.toml +++ b/tee-worker/common/core-primitives/storage/Cargo.toml @@ -23,6 +23,8 @@ sp-trie = { workspace = true } itp-types = { workspace = true } +litentry-hex-utils = { workspace = true } + [dev-dependencies] sp-state-machine = { workspace = true, features = ["std"] } diff --git a/tee-worker/common/core-primitives/storage/src/keys.rs b/tee-worker/common/core-primitives/storage/src/keys.rs index 43de4f667e..5771bd8c03 100644 --- a/tee-worker/common/core-primitives/storage/src/keys.rs +++ b/tee-worker/common/core-primitives/storage/src/keys.rs @@ -15,9 +15,11 @@ */ -use codec::Encode; +use alloc::{string::String, vec::Vec}; +use codec::{Decode, Encode}; use frame_metadata::v14::StorageHasher; -use sp_std::vec::Vec; +use frame_support::{Blake2_128Concat, ReversibleStorageHasher}; +use litentry_hex_utils::decode_hex; pub fn storage_value_key(module_prefix: &str, storage_prefix: &str) -> Vec { let mut bytes = sp_core::twox_128(module_prefix.as_bytes()).to_vec(); @@ -37,6 +39,16 @@ pub fn storage_map_key( bytes } +pub fn extract_blake2_128concat_key(raw_storage_key: &[u8]) -> Option { + let mut raw_key = Blake2_128Concat::reverse(raw_storage_key); + K::decode(&mut raw_key).ok() +} + +pub fn decode_storage_key(raw_key: Vec) -> Option> { + let hex_key = String::decode(&mut raw_key.as_slice()).unwrap_or_default(); + decode_hex(hex_key).ok() +} + pub fn storage_double_map_key( module_prefix: &str, storage_prefix: &str, diff --git a/tee-worker/common/core-primitives/storage/src/lib.rs b/tee-worker/common/core-primitives/storage/src/lib.rs index 3a3b6f2a6d..77a087e23e 100644 --- a/tee-worker/common/core-primitives/storage/src/lib.rs +++ b/tee-worker/common/core-primitives/storage/src/lib.rs @@ -23,6 +23,8 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam #[cfg(all(not(feature = "std"), feature = "sgx"))] extern crate sgx_tstd as std; +extern crate alloc; + pub use error::Error; pub use frame_metadata::v14::StorageHasher; pub use keys::*; diff --git a/tee-worker/common/core-primitives/test/src/mock/onchain_mock.rs b/tee-worker/common/core-primitives/test/src/mock/onchain_mock.rs index a0163f8df0..021875620e 100644 --- a/tee-worker/common/core-primitives/test/src/mock/onchain_mock.rs +++ b/tee-worker/common/core-primitives/test/src/mock/onchain_mock.rs @@ -223,7 +223,11 @@ impl EnclaveOnChainOCallApi for OnchainMock { Ok(entries) } - fn get_storage_keys(&self, _key_prefix: Vec) -> Result>, itp_ocall_api::Error> { + fn get_storage_keys>( + &self, + _key_prefix: Vec, + _header: Option<&H>, + ) -> Result>, itp_ocall_api::Error> { Ok(Default::default()) } } diff --git a/tee-worker/common/litentry/primitives/src/lib.rs b/tee-worker/common/litentry/primitives/src/lib.rs index 298d8090ed..0615b49327 100644 --- a/tee-worker/common/litentry/primitives/src/lib.rs +++ b/tee-worker/common/litentry/primitives/src/lib.rs @@ -72,6 +72,7 @@ pub use parentchain_primitives::{ }, decl_rsa_request, identity::*, + omni_account::*, teebag::*, AccountId as ParentchainAccountId, Balance as ParentchainBalance, BlockNumber as ParentchainBlockNumber, ErrorDetail, ErrorString, Hash as ParentchainHash, diff --git a/tee-worker/identity/core-primitives/stf-executor/Cargo.toml b/tee-worker/identity/core-primitives/stf-executor/Cargo.toml index e77096f69e..260edbdd5d 100644 --- a/tee-worker/identity/core-primitives/stf-executor/Cargo.toml +++ b/tee-worker/identity/core-primitives/stf-executor/Cargo.toml @@ -15,6 +15,7 @@ itp-node-api = { workspace = true } itp-ocall-api = { workspace = true } itp-sgx-crypto = { workspace = true } itp-sgx-externalities = { workspace = true } +itp-sgx-io = { workspace = true } itp-stf-interface = { workspace = true } itp-stf-primitives = { workspace = true } itp-stf-state-handler = { workspace = true } diff --git a/tee-worker/identity/enclave-runtime/Cargo.lock b/tee-worker/identity/enclave-runtime/Cargo.lock index 57c5ec6c5a..3852a51f84 100644 --- a/tee-worker/identity/enclave-runtime/Cargo.lock +++ b/tee-worker/identity/enclave-runtime/Cargo.lock @@ -2016,6 +2016,7 @@ dependencies = [ "itp-ocall-api", "itp-sgx-crypto", "itp-sgx-externalities", + "itp-sgx-io", "itp-stf-interface", "itp-stf-primitives", "itp-stf-state-handler", @@ -2597,6 +2598,7 @@ dependencies = [ "frame-support", "hash-db 0.15.2", "itp-types", + "litentry-hex-utils", "parity-scale-codec", "sgx_tstd", "sp-core", diff --git a/tee-worker/identity/enclave-runtime/src/ocall/on_chain_ocall.rs b/tee-worker/identity/enclave-runtime/src/ocall/on_chain_ocall.rs index e80c1fb112..124f7fabd9 100644 --- a/tee-worker/identity/enclave-runtime/src/ocall/on_chain_ocall.rs +++ b/tee-worker/identity/enclave-runtime/src/ocall/on_chain_ocall.rs @@ -125,9 +125,13 @@ impl EnclaveOnChainOCallApi for OcallApi { Ok(storage_entries) } - fn get_storage_keys(&self, key_prefix: Vec) -> Result>> { - // always using the latest state - we need to support optional header - let requests = vec![WorkerRequest::ChainStorageKeys(key_prefix, None)]; + fn get_storage_keys>( + &self, + key_prefix: Vec, + header: Option<&H>, + ) -> Result>> { + let header_hash = header.map(|h| h.hash()); + let requests = vec![WorkerRequest::ChainStorageKeys(key_prefix, header_hash)]; let responses: Vec>> = self .worker_request::>(requests, &ParentchainId::Litentry)? diff --git a/tee-worker/identity/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs b/tee-worker/identity/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs index 7f68b55a69..67a1b4ea64 100644 --- a/tee-worker/identity/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs +++ b/tee-worker/identity/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs @@ -84,7 +84,11 @@ impl EnclaveOnChainOCallApi for ProposeToImportOCallApi { todo!() } - fn get_storage_keys(&self, _key_prefix: Vec) -> Result>> { + fn get_storage_keys>( + &self, + _key_prefix: Vec, + _header: Option<&H>, + ) -> Result>> { todo!() } } diff --git a/tee-worker/identity/litentry/core/assertion-build/src/a13.rs b/tee-worker/identity/litentry/core/assertion-build/src/a13.rs index 0f46664799..8c1cd1904a 100644 --- a/tee-worker/identity/litentry/core/assertion-build/src/a13.rs +++ b/tee-worker/identity/litentry/core/assertion-build/src/a13.rs @@ -24,6 +24,7 @@ use crate::*; use codec::Decode; use frame_support::storage::storage_prefix; use itp_ocall_api::EnclaveOnChainOCallApi; +use itp_types::parentchain::Header; use lc_credentials::IssuerRuntimeVersion; use litentry_primitives::Address32; @@ -39,7 +40,7 @@ pub fn build( debug!("Assertion A13 build, who: {:?}", account_id_to_string(&who)); let key_prefix = storage_prefix(b"VCManagement", b"Delegatee"); - let response = ocall_api.get_storage_keys(key_prefix.into()).map_err(|_| { + let response = ocall_api.get_storage_keys::
(key_prefix.into(), None).map_err(|_| { Error::RequestVCFailed(Assertion::A13(who.clone()), ErrorDetail::ParseError) })?; let keys: Vec = response diff --git a/tee-worker/identity/litentry/core/omni-account/Cargo.toml b/tee-worker/identity/litentry/core/omni-account/Cargo.toml new file mode 100644 index 0000000000..0b36e26d6e --- /dev/null +++ b/tee-worker/identity/litentry/core/omni-account/Cargo.toml @@ -0,0 +1,32 @@ +[package] +authors = ["Trust Computing GmbH "] +edition = "2021" +name = "lc-omni-account" +version = "0.1.0" + +[dependencies] +litentry-primitives = { workspace = true } + +itp-ocall-api = { workspace = true } +itp-storage = { workspace = true } +itp-types = { workspace = true } + +frame-support = { workspace = true } +lazy_static = { workspace = true } +log = { workspace = true } +sp-core = { workspace = true } + +sgx_tstd = { workspace = true, features = ["net", "thread"], optional = true } + +[features] +default = ["std"] +std = [ + "litentry-primitives/std", + "frame-support/std", + "itp-storage/std", + "itp-types/std", +] +sgx = [ + "litentry-primitives/sgx", + "sgx_tstd", +] diff --git a/tee-worker/identity/litentry/core/omni-account/src/in_memory_store.rs b/tee-worker/identity/litentry/core/omni-account/src/in_memory_store.rs new file mode 100644 index 0000000000..30da7a4234 --- /dev/null +++ b/tee-worker/identity/litentry/core/omni-account/src/in_memory_store.rs @@ -0,0 +1,77 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{AccountId, BTreeMap, Error, MemberAccount, OmniAccounts, Vec}; +use lazy_static::lazy_static; + +#[cfg(feature = "std")] +use std::sync::RwLock; +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +lazy_static! { + static ref STORE: RwLock = RwLock::new(BTreeMap::new()); +} + +pub struct InMemoryStore; + +impl InMemoryStore { + pub fn get(&self, owner: AccountId) -> Result>, Error> { + let omni_account_members = STORE + .read() + .map_err(|_| { + log::error!("[InMemoryStore] Lock poisoning"); + Error::LockPoisoning + })? + .get(&owner) + .cloned(); + + Ok(omni_account_members) + } + + pub fn insert(&self, account_id: AccountId, members: Vec) -> Result<(), Error> { + STORE + .write() + .map_err(|_| { + log::error!("[InMemoryStore] Lock poisoning"); + Error::LockPoisoning + })? + .insert(account_id, members); + + Ok(()) + } + + pub fn remove(&self, account_id: AccountId) -> Result<(), Error> { + STORE + .write() + .map_err(|_| { + log::error!("[InMemoryStore] Lock poisoning"); + Error::LockPoisoning + })? + .remove(&account_id); + + Ok(()) + } + + pub fn load(&self, accounts: OmniAccounts) -> Result<(), Error> { + *STORE.write().map_err(|_| { + log::error!("[InMemoryStore] Lock poisoning"); + Error::LockPoisoning + })? = accounts; + + Ok(()) + } +} diff --git a/tee-worker/identity/litentry/core/omni-account/src/lib.rs b/tee-worker/identity/litentry/core/omni-account/src/lib.rs new file mode 100644 index 0000000000..506ff11c41 --- /dev/null +++ b/tee-worker/identity/litentry/core/omni-account/src/lib.rs @@ -0,0 +1,43 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +pub extern crate alloc; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +mod repository; +pub use repository::*; + +mod in_memory_store; +pub use in_memory_store::InMemoryStore; + +use alloc::{collections::btree_map::BTreeMap, vec::Vec}; +use itp_types::parentchain::{AccountId, Header, ParentchainId}; +use litentry_primitives::MemberAccount; + +pub type OmniAccounts = BTreeMap>; + +#[derive(Debug)] +pub enum Error { + LockPoisoning, + OCallApiError(&'static str), +} diff --git a/tee-worker/identity/litentry/core/omni-account/src/repository.rs b/tee-worker/identity/litentry/core/omni-account/src/repository.rs new file mode 100644 index 0000000000..c12993d1eb --- /dev/null +++ b/tee-worker/identity/litentry/core/omni-account/src/repository.rs @@ -0,0 +1,95 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{AccountId, Error, Header, MemberAccount, OmniAccounts, ParentchainId}; +use alloc::vec::Vec; +use frame_support::storage::storage_prefix; +use itp_ocall_api::EnclaveOnChainOCallApi; +use itp_storage::{ + decode_storage_key, extract_blake2_128concat_key, storage_map_key, StorageHasher, +}; + +pub trait GetAccountStoresRepository { + fn get_by_account_id(&self, account_id: AccountId) + -> Result>, Error>; + fn get_all(&self) -> Result; +} + +pub struct OmniAccountRepository { + ocall_api: OCallApi, + header: Header, +} + +impl OmniAccountRepository { + pub fn new(ocall_api: OCallApi, header: Header) -> Self { + Self { ocall_api, header } + } + + pub fn set_header(&mut self, header: Header) { + self.header = header; + } +} + +impl GetAccountStoresRepository + for OmniAccountRepository +{ + fn get_by_account_id(&self, owner: AccountId) -> Result>, Error> { + let storage_key = storage_map_key( + "OmniAccount", + "AccountStore", + &owner, + &StorageHasher::Blake2_128Concat, + ); + let storage_entry = self + .ocall_api + .get_storage_verified(storage_key, &self.header, &ParentchainId::Litentry) + .map_err(|_| Error::OCallApiError("Failed to get storage"))?; + let member_accounts = storage_entry.value().to_owned(); + + Ok(member_accounts) + } + + fn get_all(&self) -> Result { + let account_store_key_prefix = storage_prefix(b"OmniAccount", b"AccountStore"); + let account_store_storage_keys_response = self + .ocall_api + .get_storage_keys(account_store_key_prefix.into(), Some(&self.header)) + .map_err(|_| Error::OCallApiError("Failed to get storage keys"))?; + let account_store_storage_keys = account_store_storage_keys_response + .into_iter() + .filter_map(decode_storage_key) + .collect::>>(); + let omni_accounts: OmniAccounts = self + .ocall_api + .get_multiple_storages_verified( + account_store_storage_keys, + &self.header, + &ParentchainId::Litentry, + ) + .map_err(|_| Error::OCallApiError("Failed to get multiple storages"))? + .into_iter() + .filter_map(|entry| { + // TODO: double check this + let storage_key = decode_storage_key(entry.key)?; + let account_id: AccountId = extract_blake2_128concat_key(&storage_key)?; + let member_accounts: Vec = entry.value?; + Some((account_id, member_accounts)) + }) + .collect(); + + Ok(omni_accounts) + } +}