From e554a3ae5720ec9ba44da73f2d62978cda2c5d21 Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Mon, 30 Sep 2024 15:59:59 +0000 Subject: [PATCH 01/13] relocate aes key --- tee-worker/Cargo.lock | 4 + .../bitacross/enclave-runtime/Cargo.lock | 3 + .../src/initialization/global_components.rs | 3 +- .../core-primitives/sgx/crypto/Cargo.toml | 10 +- .../core-primitives/sgx/crypto/src/aes256.rs | 293 ++++++++++++++++++ .../core-primitives/sgx/crypto/src/lib.rs | 4 +- .../common/litentry/primitives/src/aes.rs | 134 -------- .../common/litentry/primitives/src/lib.rs | 3 +- .../identity/app-libs/stf/src/trusted_call.rs | 2 +- .../identity/cli/src/benchmark/request_vc.rs | 6 +- .../commands/litentry/request_vc.rs | 6 +- .../identity/enclave-runtime/Cargo.lock | 3 + 12 files changed, 325 insertions(+), 146 deletions(-) create mode 100644 tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs delete mode 100644 tee-worker/common/litentry/primitives/src/aes.rs diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index 10c958bc63..5a1a1078a5 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -4268,6 +4268,9 @@ dependencies = [ "log 0.4.20", "ofb", "parity-scale-codec", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", + "ring 0.16.20", "secp256k1 0.28.0", "serde_json 1.0.103", "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3)", @@ -4276,6 +4279,7 @@ dependencies = [ "sgx_tstd", "sgx_types", "sp-core", + "sp-std 5.0.0", ] [[package]] diff --git a/tee-worker/bitacross/enclave-runtime/Cargo.lock b/tee-worker/bitacross/enclave-runtime/Cargo.lock index 0062a3972d..47e487b333 100644 --- a/tee-worker/bitacross/enclave-runtime/Cargo.lock +++ b/tee-worker/bitacross/enclave-runtime/Cargo.lock @@ -2429,6 +2429,8 @@ dependencies = [ "log 0.4.21", "ofb", "parity-scale-codec", + "rand 0.7.3", + "ring 0.16.20", "secp256k1 0.28.0", "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3)", "sgx_crypto_helper", @@ -2436,6 +2438,7 @@ dependencies = [ "sgx_tstd", "sgx_types", "sp-core", + "sp-std", ] [[package]] diff --git a/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs b/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs index 6e60d93af5..053e8d4b51 100644 --- a/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs +++ b/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs @@ -68,7 +68,7 @@ use itp_sgx_crypto::{ ecdsa::{Pair as EcdsaPair, Seal as EcdsaSeal}, key_repository::KeyRepository, schnorr::{Pair as SchnorrPair, Seal as SchnorrSeal}, - Aes, AesSeal, Ed25519Seal, Rsa3072Seal, + Aes, AesSeal, Ed25519Seal, IDGraphKey, IDGraphKeySeal, Rsa3072Seal, }; use itp_stf_executor::{ enclave_signer::StfEnclaveSigner, executor::StfExecutor, getter_executor::GetterExecutor, @@ -100,6 +100,7 @@ pub type EnclaveTrustedCallSigned = TrustedCallSigned; pub type EnclaveStf = Stf; pub type EnclaveStateKeyRepository = KeyRepository; pub type EnclaveShieldingKeyRepository = KeyRepository; +// pub type EnclaveIDGraphKeyRepository = KeyRepository<, EcdsaSeal>; pub type EnclaveSigningKeyRepository = KeyRepository; pub type EnclaveBitcoinKeyRepository = KeyRepository; pub type EnclaveEthereumKeyRepository = KeyRepository; diff --git a/tee-worker/common/core-primitives/sgx/crypto/Cargo.toml b/tee-worker/common/core-primitives/sgx/crypto/Cargo.toml index 2aa3a3b5a4..4c560037d5 100644 --- a/tee-worker/common/core-primitives/sgx/crypto/Cargo.toml +++ b/tee-worker/common/core-primitives/sgx/crypto/Cargo.toml @@ -11,16 +11,20 @@ hex = { workspace = true } k256 = { workspace = true, features = ["ecdsa-core", "schnorr", "alloc"] } log = { workspace = true } ofb = { workspace = true } +rand = { workspace = true, optional = true } +rand-sgx = { workspace = true, optional = true } +ring = { workspace = true } secp256k1 = { workspace = true, features = ["alloc", "recovery"] } serde_json = { workspace = true, optional = true } - serde_json_sgx = { workspace = true, optional = true } + sgx_crypto_helper = { workspace = true } sgx_rand = { workspace = true, optional = true } sgx_tstd = { workspace = true, optional = true } sgx_types = { workspace = true } sp-core = { workspace = true } +sp-std = { workspace = true } itp-sgx-io = { workspace = true } itp-sgx-temp-dir = { workspace = true, optional = true } @@ -30,8 +34,11 @@ default = ["std"] std = [ "codec/std", "log/std", + "rand", + "ring/std", "itp-sgx-io/std", "sp-core/std", + "sp-std/std", "serde_json/std", "sgx_crypto_helper/default", ] @@ -39,6 +46,7 @@ sgx = [ "sgx_crypto_helper/mesalock_sgx", "sgx_tstd", "sgx_rand", + "rand-sgx", "itp-sgx-io/sgx", "serde_json_sgx", ] diff --git a/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs b/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs new file mode 100644 index 0000000000..30f1f8dbe1 --- /dev/null +++ b/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs @@ -0,0 +1,293 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use codec::{Decode, Encode}; +use rand::Rng; +pub use ring::aead::{MAX_TAG_LEN, NONCE_LEN}; +use ring::{ + aead::{Aad, BoundKey, LessSafeKey, Nonce, NonceSequence, SealingKey, UnboundKey, AES_256_GCM}, + error::Unspecified, +}; +use std::vec::Vec; + +// we use 256-bit AES-GCM as request enc/dec key +pub const AES_KEY_LEN: usize = 32; + +pub type Aes256Key = [u8; AES_KEY_LEN]; +pub type Aes256KeyNonce = [u8; NONCE_LEN]; + +/// File name of the sealed seed file. +pub const SEALED_SIGNER_SEED_FILE: &str = "aes256_key_sealed.bin"; + +// all-in-one struct containing the encrypted ciphertext with other +// metadata that is required for decryption +// +// by default a postfix tag is used => last 16 bytes of ciphertext is MAC tag +#[derive(Debug, Default, Clone, Eq, PartialEq, Encode, Decode)] +pub struct AesOutput { + pub ciphertext: Vec, + pub aad: Vec, + pub nonce: Aes256KeyNonce, // IV +} + +// Returns the default if any error happens +// We don't propagate the error to upper level as this function is used in too many places, +// it's too verbose to handle them all and pass back to the parentchain as events. +// We rely on the parentchain event consumers to handle them correctly (and they kind of +// have to, because they'll find all fields are 0) +pub fn aes_encrypt_default(key: &Aes256Key, data: &[u8]) -> AesOutput { + let mut in_out = data.to_vec(); + + let mut nonce = RingAeadNonceSequence::new(); + if nonce.advance().is_ok() { + let aad = b""; + if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { + let mut sealing_key = SealingKey::new(unbound_key, nonce.clone()); + if sealing_key.seal_in_place_append_tag(Aad::from(aad), &mut in_out).is_ok() { + return AesOutput { + ciphertext: in_out.to_vec(), + aad: aad.to_vec(), + nonce: nonce.nonce, + } + } + } + } + + AesOutput::default() +} + +// use LessSafeKey::seal_in_place_append_tag to encrypt the data using the given nonce +// don't be scared by the name, it's similar to `SealingKey::seal_in_place_append_tag`, +// except that it accepts an arbitrary nonce. +// It's only used by the one-off verification message calculation. +pub fn aes_encrypt_nonce(key: &Aes256Key, data: &[u8], nonce: Aes256KeyNonce) -> AesOutput { + let mut in_out = data.to_vec(); + let aad = b""; + if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { + let less_safe_key = LessSafeKey::new(unbound_key); + if less_safe_key + .seal_in_place_append_tag( + Nonce::assume_unique_for_key(nonce), + Aad::from(aad), + &mut in_out, + ) + .is_ok() + { + return AesOutput { ciphertext: in_out.to_vec(), aad: aad.to_vec(), nonce } + } + } + + AesOutput::default() +} + +pub fn aes_decrypt(key: &Aes256Key, data: &mut AesOutput) -> Option> { + let in_out = data.ciphertext.as_mut(); + if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { + let less_safe_key = LessSafeKey::new(unbound_key); + return less_safe_key + .open_in_place( + Nonce::assume_unique_for_key(data.nonce), + Aad::from(data.aad.clone()), + in_out, + ) + .ok() + .map(|data| data.to_vec()) + } + None +} + +#[derive(Clone)] +struct RingAeadNonceSequence { + pub nonce: Aes256KeyNonce, +} + +impl RingAeadNonceSequence { + fn new() -> RingAeadNonceSequence { + RingAeadNonceSequence { nonce: [0u8; NONCE_LEN] } + } +} + +impl NonceSequence for RingAeadNonceSequence { + fn advance(&mut self) -> core::result::Result { + let nonce = Nonce::assume_unique_for_key(self.nonce); + let nonce_vec = rand::thread_rng().gen::(); + self.nonce.copy_from_slice(&nonce_vec[0..NONCE_LEN]); + Ok(nonce) + } +} + +#[cfg(feature = "sgx")] +pub mod sgx { + use super::*; + use crate::{ + error::{Error, Result}, + key_repository::KeyRepository, + }; + use itp_sgx_io::{seal, unseal, SealedIO}; + use log::*; + use sgx_rand::{Rng, StdRng}; + use std::{ + path::PathBuf, + sgxfs::SgxFile, + string::{String, ToString}, + }; + + /// Gets a repository for an Rsa3072 keypair and initializes + /// a fresh key pair if it doesn't exist at `path`. + pub fn create_aes256_repository( + path: PathBuf, + key_file_prefix: &str, + key: Option, + ) -> Result> { + let seal = Seal::new(path, key_file_prefix.to_string()); + Ok(KeyRepository::new(seal.init(key)?, seal.into())) + } + + #[derive(Clone, Debug)] + pub struct Seal { + base_path: PathBuf, + key_file_prefix: String, + } + + impl Seal { + pub fn new(base_path: PathBuf, key_file_prefix: String) -> Self { + Self { base_path, key_file_prefix } + } + + pub fn path(&self) -> PathBuf { + self.base_path + .join(self.key_file_prefix.clone() + "_" + SEALED_SIGNER_SEED_FILE) + } + } + + impl Seal { + fn unseal_key(&self) -> Result { + self.unseal() + } + + pub fn exists(&self) -> bool { + SgxFile::open(self.path()).is_ok() + } + + pub fn init(&self, key: Option) -> Result { + if !self.exists() || key.is_some() { + if !self.exists() { + info!("Keyfile not found, creating new! {}", self.path().display()); + } + if key.is_some() { + info!("New key provided, it will be sealed!"); + } + let key = if let Some(key) = key { + key + } else { + let mut seed = Aes256Key::default(); + let mut rand = StdRng::new()?; + rand.fill_bytes(&mut seed); + seed + }; + seal(&key, self.path())?; + } + self.unseal_key() + } + } + + impl SealedIO for Seal { + type Error = Error; + type Unsealed = Aes256Key; + + fn unseal(&self) -> Result { + Ok(unseal(self.path()).map(|b| Decode::decode(&mut b.as_slice()))??) + } + + fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> { + Ok(unsealed.using_encoded(|bytes| seal(bytes, self.path()))?) + } + } +} + +#[cfg(feature = "test")] +pub mod sgx_tests { + use super::{sgx::*, *}; + use crate::key_repository::AccessKey; + use itp_sgx_temp_dir::TempDir; + + pub fn aes256_creating_repository_with_same_path_and_prefix_results_in_same_key() { + let prefix = "test"; + let temp_dir = TempDir::with_prefix( + "aes256_creating_repository_with_same_path_and_prefix_results_in_same_key", + ) + .unwrap(); + let temp_path = temp_dir.path().to_path_buf(); + let key1 = create_aes256_repository(temp_path.clone(), prefix, None) + .unwrap() + .retrieve_key() + .unwrap(); + let key2 = create_aes256_repository(temp_path, prefix, None) + .unwrap() + .retrieve_key() + .unwrap(); + assert_eq!(key1, key2); + } + + pub fn aes256_creating_repository_with_same_path_and_prefix_but_new_key_results_in_new_key() { + let prefix = "test"; + let temp_dir = TempDir::with_prefix( + "aes256_creating_repository_with_same_path_and_prefix_but_new_key_results_in_new_key", + ) + .unwrap(); + let temp_path = temp_dir.path().to_path_buf(); + + let new_key: [u8; 32] = [1u8; 32]; + let first_key = create_aes256_repository(temp_path.clone(), prefix, None) + .unwrap() + .retrieve_key() + .unwrap(); + let second_key = create_aes256_repository(temp_path, prefix, Some(new_key)) + .unwrap() + .retrieve_key() + .unwrap(); + + assert_ne!(first_key, second_key); + assert_eq!(second_key, new_key); + } + + // pub fn aes_sealing_works() { + // let temp_dir = TempDir::with_prefix("aes_sealing_works").unwrap(); + // let seal = AesSeal::new(temp_dir.path().to_path_buf()); + + // // Create new sealed keys and unseal them + // assert!(!seal.exists()); + // seal.create_sealed_if_absent().unwrap(); + // let key = seal.unseal_key().unwrap(); + + // assert!(seal.exists()); + + // // Should not change anything because the key is already there. + // seal.create_sealed_if_absent().unwrap(); + // let key_same = seal.unseal_key().unwrap(); + + // assert_eq!(key, key_same); + + // // Should overwrite previous keys. + // seal.create_sealed().unwrap(); + // let key_different = seal.unseal_key().unwrap(); + + // assert_ne!(key_different, key); + // } +} diff --git a/tee-worker/common/core-primitives/sgx/crypto/src/lib.rs b/tee-worker/common/core-primitives/sgx/crypto/src/lib.rs index f52d555abb..096468c32c 100644 --- a/tee-worker/common/core-primitives/sgx/crypto/src/lib.rs +++ b/tee-worker/common/core-primitives/sgx/crypto/src/lib.rs @@ -29,10 +29,12 @@ extern crate sgx_tstd as std; // re-export module to properly feature gate sgx and regular std environment #[cfg(all(not(feature = "std"), feature = "sgx"))] pub mod sgx_reexport_prelude { + pub use rand_sgx as rand; pub use serde_json_sgx as serde_json; } pub mod aes; +pub mod aes256; pub mod ecdsa; pub mod ed25519; pub mod ed25519_derivation; @@ -42,7 +44,7 @@ pub mod rsa3072; pub mod schnorr; pub mod traits; -pub use self::{aes::*, ecdsa::*, ed25519::*, rsa3072::*}; +pub use self::{aes::*, aes256::*, ecdsa::*, ed25519::*, rsa3072::*}; pub use error::*; pub use traits::*; diff --git a/tee-worker/common/litentry/primitives/src/aes.rs b/tee-worker/common/litentry/primitives/src/aes.rs deleted file mode 100644 index 8abbb7b149..0000000000 --- a/tee-worker/common/litentry/primitives/src/aes.rs +++ /dev/null @@ -1,134 +0,0 @@ -// 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(all(not(feature = "std"), feature = "sgx"))] -extern crate sgx_tstd as std; - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -extern crate rand_sgx as rand; - -use crate::{Decode, Encode, Vec}; - -use rand::Rng; - -use ring::{ - aead::{Aad, BoundKey, LessSafeKey, Nonce, NonceSequence, SealingKey, UnboundKey, AES_256_GCM}, - error::Unspecified, -}; - -// we use 256-bit AES-GCM as request enc/dec key -pub const REQUEST_AES_KEY_LEN: usize = 32; -pub use ring::aead::{MAX_TAG_LEN, NONCE_LEN}; - -pub type RequestAesKey = [u8; REQUEST_AES_KEY_LEN]; -pub type RequestAesKeyNonce = [u8; NONCE_LEN]; - -// all-in-one struct containing the encrypted ciphertext with other -// metadata that is required for decryption -// -// by default a postfix tag is used => last 16 bytes of ciphertext is MAC tag -#[derive(Debug, Default, Clone, Eq, PartialEq, Encode, Decode)] -pub struct AesOutput { - pub ciphertext: Vec, - pub aad: Vec, - pub nonce: RequestAesKeyNonce, // IV -} - -// Returns the default if any error happens -// We don't propagate the error to upper level as this function is used in too many places, -// it's too verbose to handle them all and pass back to the parentchain as events. -// We rely on the parentchain event consumers to handle them correctly (and they kind of -// have to, because they'll find all fields are 0) -pub fn aes_encrypt_default(key: &RequestAesKey, data: &[u8]) -> AesOutput { - let mut in_out = data.to_vec(); - - let mut nonce = RingAeadNonceSequence::new(); - if nonce.advance().is_ok() { - let aad = b""; - if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { - let mut sealing_key = SealingKey::new(unbound_key, nonce.clone()); - if sealing_key.seal_in_place_append_tag(Aad::from(aad), &mut in_out).is_ok() { - return AesOutput { - ciphertext: in_out.to_vec(), - aad: aad.to_vec(), - nonce: nonce.nonce, - } - } - } - } - - AesOutput::default() -} - -// use LessSafeKey::seal_in_place_append_tag to encrypt the data using the given nonce -// don't be scared by the name, it's similar to `SealingKey::seal_in_place_append_tag`, -// except that it accepts an arbitrary nonce. -// It's only used by the one-off verification message calculation. -pub fn aes_encrypt_nonce(key: &RequestAesKey, data: &[u8], nonce: RequestAesKeyNonce) -> AesOutput { - let mut in_out = data.to_vec(); - let aad = b""; - if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { - let less_safe_key = LessSafeKey::new(unbound_key); - if less_safe_key - .seal_in_place_append_tag( - Nonce::assume_unique_for_key(nonce), - Aad::from(aad), - &mut in_out, - ) - .is_ok() - { - return AesOutput { ciphertext: in_out.to_vec(), aad: aad.to_vec(), nonce } - } - } - - AesOutput::default() -} - -pub fn aes_decrypt(key: &RequestAesKey, data: &mut AesOutput) -> Option> { - let in_out = data.ciphertext.as_mut(); - if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { - let less_safe_key = LessSafeKey::new(unbound_key); - return less_safe_key - .open_in_place( - Nonce::assume_unique_for_key(data.nonce), - Aad::from(data.aad.clone()), - in_out, - ) - .ok() - .map(|data| data.to_vec()) - } - None -} - -#[derive(Clone)] -pub struct RingAeadNonceSequence { - pub nonce: RequestAesKeyNonce, -} - -impl RingAeadNonceSequence { - fn new() -> RingAeadNonceSequence { - RingAeadNonceSequence { nonce: [0u8; NONCE_LEN] } - } -} - -impl NonceSequence for RingAeadNonceSequence { - fn advance(&mut self) -> Result { - let nonce = Nonce::assume_unique_for_key(self.nonce); - let nonce_vec = rand::thread_rng().gen::(); - self.nonce.copy_from_slice(&nonce_vec[0..NONCE_LEN]); - Ok(nonce) - } -} diff --git a/tee-worker/common/litentry/primitives/src/lib.rs b/tee-worker/common/litentry/primitives/src/lib.rs index 2a14a12b82..63046c3a79 100644 --- a/tee-worker/common/litentry/primitives/src/lib.rs +++ b/tee-worker/common/litentry/primitives/src/lib.rs @@ -23,7 +23,6 @@ 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 aes; mod aes_request; mod bitcoin_address; mod bitcoin_signature; @@ -32,7 +31,6 @@ mod plain_request; mod stf_request; mod validation_data; -pub use aes::*; pub use aes_request::*; pub use bitcoin_address::*; pub use bitcoin_signature::*; @@ -43,6 +41,7 @@ pub use validation_data::*; use bitcoin::sign_message::{signed_msg_hash, MessageSignature}; use codec::{Decode, Encode, MaxEncodedLen}; +pub use itp_sgx_crypto::aes256::{Aes256Key as RequestAesKey, *}; use itp_sgx_crypto::ShieldingCryptoDecrypt; use log::error; pub use pallet_teebag::{ diff --git a/tee-worker/identity/app-libs/stf/src/trusted_call.rs b/tee-worker/identity/app-libs/stf/src/trusted_call.rs index 0fc8c6f11c..efbbb484a4 100644 --- a/tee-worker/identity/app-libs/stf/src/trusted_call.rs +++ b/tee-worker/identity/app-libs/stf/src/trusted_call.rs @@ -54,7 +54,7 @@ use litentry_hex_utils::hex_encode; pub use litentry_primitives::{ aes_encrypt_default, all_evm_web3networks, all_substrate_web3networks, AesOutput, Assertion, ErrorDetail, IMPError, Identity, LitentryMultiSignature, ParentchainBlockNumber, RequestAesKey, - RequestAesKeyNonce, VCMPError, ValidationData, Web3Network, + VCMPError, ValidationData, Web3Network, }; use log::*; use sp_core::{ diff --git a/tee-worker/identity/cli/src/benchmark/request_vc.rs b/tee-worker/identity/cli/src/benchmark/request_vc.rs index 2792e94172..552327c733 100644 --- a/tee-worker/identity/cli/src/benchmark/request_vc.rs +++ b/tee-worker/identity/cli/src/benchmark/request_vc.rs @@ -15,7 +15,7 @@ use itp_stf_primitives::{ traits::TrustedCallSigning, types::{KeyPair, TrustedOperation}, }; -use litentry_primitives::{RequestAesKey, ShardIdentifier, REQUEST_AES_KEY_LEN}; +use litentry_primitives::{RequestAesKey, ShardIdentifier, AES_KEY_LEN}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::Pair; @@ -161,6 +161,6 @@ impl BenchmarkRequestVcCommand { } fn random_aes_key() -> RequestAesKey { - let random: Vec = (0..REQUEST_AES_KEY_LEN).map(|_| rand::random::()).collect(); - random[0..REQUEST_AES_KEY_LEN].try_into().unwrap() + let random: Vec = (0..AES_KEY_LEN).map(|_| rand::random::()).collect(); + random[0..AES_KEY_LEN].try_into().unwrap() } diff --git a/tee-worker/identity/cli/src/trusted_base_cli/commands/litentry/request_vc.rs b/tee-worker/identity/cli/src/trusted_base_cli/commands/litentry/request_vc.rs index d684495f05..3b137f4fe8 100644 --- a/tee-worker/identity/cli/src/trusted_base_cli/commands/litentry/request_vc.rs +++ b/tee-worker/identity/cli/src/trusted_base_cli/commands/litentry/request_vc.rs @@ -28,7 +28,7 @@ use ita_stf::{trusted_call_result::RequestVCResult, Index, TrustedCall}; use itp_stf_primitives::{traits::TrustedCallSigning, types::KeyPair}; use litentry_primitives::{ aes_decrypt, Assertion, BoundedWeb3Network, Identity, ParameterString, RequestAesKey, - Web3Network, REQUEST_AES_KEY_LEN, + Web3Network, AES_KEY_LEN, }; use sp_core::Pair; @@ -163,8 +163,8 @@ impl RequestVcCommand { } fn random_aes_key() -> RequestAesKey { - let random: Vec = (0..REQUEST_AES_KEY_LEN).map(|_| rand::random::()).collect(); - random[0..REQUEST_AES_KEY_LEN].try_into().unwrap() + let random: Vec = (0..AES_KEY_LEN).map(|_| rand::random::()).collect(); + random[0..AES_KEY_LEN].try_into().unwrap() } } diff --git a/tee-worker/identity/enclave-runtime/Cargo.lock b/tee-worker/identity/enclave-runtime/Cargo.lock index 34b8f1631d..5b1d0fcbb2 100644 --- a/tee-worker/identity/enclave-runtime/Cargo.lock +++ b/tee-worker/identity/enclave-runtime/Cargo.lock @@ -2552,6 +2552,8 @@ dependencies = [ "log", "ofb", "parity-scale-codec", + "rand 0.7.3", + "ring 0.16.20", "secp256k1 0.28.0", "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3)", "sgx_crypto_helper", @@ -2559,6 +2561,7 @@ dependencies = [ "sgx_tstd", "sgx_types", "sp-core", + "sp-std", ] [[package]] From 129151ec139aaca176e15cd746764f2a1db20d63 Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Wed, 2 Oct 2024 22:54:00 +0000 Subject: [PATCH 02/13] add skeleton --- .../app-libs/stf/src/trusted_call.rs | 2 +- .../src/initialization/global_components.rs | 1 - .../core-primitives/sgx/crypto/src/aes256.rs | 24 ----------- .../core-primitives/sgx/crypto/src/lib.rs | 5 +++ .../src/initialization/global_components.rs | 11 ++++- .../enclave-runtime/src/initialization/mod.rs | 22 ++++++---- .../enclave-runtime/src/rpc/common_api.rs | 42 +++++++++++++++++++ .../enclave-runtime/src/test/tests_main.rs | 2 + 8 files changed, 73 insertions(+), 36 deletions(-) diff --git a/tee-worker/bitacross/app-libs/stf/src/trusted_call.rs b/tee-worker/bitacross/app-libs/stf/src/trusted_call.rs index 8d8167d46b..8d29100cca 100644 --- a/tee-worker/bitacross/app-libs/stf/src/trusted_call.rs +++ b/tee-worker/bitacross/app-libs/stf/src/trusted_call.rs @@ -38,7 +38,7 @@ use itp_types::{ use itp_utils::stringify::account_id_to_string; pub use litentry_primitives::{ aes_encrypt_default, AesOutput, Identity, LitentryMultiSignature, ParentchainBlockNumber, - RequestAesKey, RequestAesKeyNonce, ValidationData, + RequestAesKey, ValidationData, }; use log::*; use sp_core::{ diff --git a/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs b/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs index 053e8d4b51..d64c580aaa 100644 --- a/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs +++ b/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs @@ -100,7 +100,6 @@ pub type EnclaveTrustedCallSigned = TrustedCallSigned; pub type EnclaveStf = Stf; pub type EnclaveStateKeyRepository = KeyRepository; pub type EnclaveShieldingKeyRepository = KeyRepository; -// pub type EnclaveIDGraphKeyRepository = KeyRepository<, EcdsaSeal>; pub type EnclaveSigningKeyRepository = KeyRepository; pub type EnclaveBitcoinKeyRepository = KeyRepository; pub type EnclaveEthereumKeyRepository = KeyRepository; diff --git a/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs b/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs index 30f1f8dbe1..64e2f2ac8a 100644 --- a/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs +++ b/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs @@ -266,28 +266,4 @@ pub mod sgx_tests { assert_ne!(first_key, second_key); assert_eq!(second_key, new_key); } - - // pub fn aes_sealing_works() { - // let temp_dir = TempDir::with_prefix("aes_sealing_works").unwrap(); - // let seal = AesSeal::new(temp_dir.path().to_path_buf()); - - // // Create new sealed keys and unseal them - // assert!(!seal.exists()); - // seal.create_sealed_if_absent().unwrap(); - // let key = seal.unseal_key().unwrap(); - - // assert!(seal.exists()); - - // // Should not change anything because the key is already there. - // seal.create_sealed_if_absent().unwrap(); - // let key_same = seal.unseal_key().unwrap(); - - // assert_eq!(key, key_same); - - // // Should overwrite previous keys. - // seal.create_sealed().unwrap(); - // let key_different = seal.unseal_key().unwrap(); - - // assert_ne!(key_different, key); - // } } diff --git a/tee-worker/common/core-primitives/sgx/crypto/src/lib.rs b/tee-worker/common/core-primitives/sgx/crypto/src/lib.rs index 096468c32c..b9c8fa9037 100644 --- a/tee-worker/common/core-primitives/sgx/crypto/src/lib.rs +++ b/tee-worker/common/core-primitives/sgx/crypto/src/lib.rs @@ -65,6 +65,11 @@ pub mod tests { aes_sealing_works, using_get_aes_repository_twice_initializes_key_only_once, }; + pub use super::aes256::sgx_tests::{ + aes256_creating_repository_with_same_path_and_prefix_but_new_key_results_in_new_key, + aes256_creating_repository_with_same_path_and_prefix_results_in_same_key, + }; + pub use super::ecdsa::sgx_tests::{ ecdsa_creating_repository_with_same_path_and_prefix_but_new_key_results_in_new_key, ecdsa_creating_repository_with_same_path_and_prefix_results_in_same_key, diff --git a/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs b/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs index 5255d5303e..9ec18fa8f6 100644 --- a/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs +++ b/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs @@ -63,7 +63,10 @@ use itp_node_api::{ metadata::{provider::NodeMetadataRepository, NodeMetadata}, }; use itp_nonce_cache::NonceCache; -use itp_sgx_crypto::{key_repository::KeyRepository, Aes, AesSeal, Ed25519Seal, Rsa3072Seal}; +use itp_sgx_crypto::{ + aes256::sgx::Seal as Aes256Seal, key_repository::KeyRepository, Aes, Aes256Key, AesSeal, + Ed25519Seal, Rsa3072Seal, +}; use itp_stf_executor::{ enclave_signer::StfEnclaveSigner, executor::StfExecutor, getter_executor::GetterExecutor, state_getter::StfStateGetter, @@ -106,6 +109,7 @@ pub type EnclaveGetter = Getter; pub type EnclaveTrustedCallSigned = TrustedCallSigned; pub type EnclaveStf = Stf; pub type EnclaveStateKeyRepository = KeyRepository; +pub type EnclaveIDGraphKeyRepository = KeyRepository; pub type EnclaveShieldingKeyRepository = KeyRepository; pub type EnclaveSigningKeyRepository = KeyRepository; pub type EnclaveStateFileIo = SgxStateFileIo; @@ -371,6 +375,11 @@ pub type EnclaveOffchainWorkerExecutor = itc_offchain_worker_executor::executor: pub static GLOBAL_STATE_KEY_REPOSITORY_COMPONENT: ComponentContainer = ComponentContainer::new("State key repository"); +/// IDGraph key repository +pub static GLOBAL_IDGRAPH_KEY_REPOSITORY_COMPONENT: ComponentContainer< + EnclaveIDGraphKeyRepository, +> = ComponentContainer::new("IDGraph key repository"); + /// Shielding key repository pub static GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT: ComponentContainer< EnclaveShieldingKeyRepository, diff --git a/tee-worker/identity/enclave-runtime/src/initialization/mod.rs b/tee-worker/identity/enclave-runtime/src/initialization/mod.rs index dabe50920b..9adf8b85ed 100644 --- a/tee-worker/identity/enclave-runtime/src/initialization/mod.rs +++ b/tee-worker/identity/enclave-runtime/src/initialization/mod.rs @@ -28,14 +28,14 @@ use crate::{ EnclaveStfEnclaveSigner, EnclaveTopPool, EnclaveTopPoolAuthor, DIRECT_RPC_REQUEST_SINK_COMPONENT, GLOBAL_ASSERTION_REPOSITORY, GLOBAL_ATTESTATION_HANDLER_COMPONENT, GLOBAL_DATA_PROVIDER_CONFIG, - GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT, GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, - GLOBAL_OCALL_API_COMPONENT, GLOBAL_RPC_WS_HANDLER_COMPONENT, - GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT, - GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT, GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT, - GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT, GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT, - GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, - GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_OBSERVER_COMPONENT, - GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT, GLOBAL_IDGRAPH_KEY_REPOSITORY_COMPONENT, + GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_OCALL_API_COMPONENT, + GLOBAL_RPC_WS_HANDLER_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, + GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT, GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT, + GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT, GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT, + GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, + GLOBAL_STATE_OBSERVER_COMPONENT, GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TOP_POOL_AUTHOR_COMPONENT, GLOBAL_WEB_SOCKET_SERVER_COMPONENT, }, @@ -91,7 +91,7 @@ use lc_evm_dynamic_assertions::repository::EvmAssertionRepository; use lc_parachain_extrinsic_task_receiver::run_parachain_extrinsic_task_receiver; use lc_stf_task_receiver::{run_stf_task_receiver, StfTaskContext}; use lc_vc_task_receiver::run_vc_handler_runner; -use litentry_primitives::BroadcastedRequest; +use litentry_primitives::{sgx::create_aes256_repository, BroadcastedRequest}; use log::*; use sgx_types::sgx_status_t; use sp_core::crypto::Pair; @@ -115,6 +115,10 @@ pub(crate) fn init_enclave( let state_key_repository = Arc::new(get_aes_repository(base_dir.clone())?); GLOBAL_STATE_KEY_REPOSITORY_COMPONENT.initialize(state_key_repository.clone()); + let idgraph_key_repository = + Arc::new(create_aes256_repository(base_dir.clone(), "idgraph", None)?); + GLOBAL_IDGRAPH_KEY_REPOSITORY_COMPONENT.initialize(idgraph_key_repository.clone()); + let integritee_light_client_seal = Arc::new(EnclaveLightClientSeal::new( base_dir.join(LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH), ParentchainId::Litentry, diff --git a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs index a0178c754f..5f1a99ca48 100644 --- a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs +++ b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs @@ -506,6 +506,48 @@ pub fn add_common_api Ok(json!(compute_hex_encoded_return_error("Could not parse params"))), } }); + + let local_state = if_development_or!(state.clone(), state); + + io_handler.add_sync_method("identity_upload_idgraph", move |params: Params| { + debug!("worker_api_direct rpc was called: identity_upload_idgraph"); + let local_state = match local_state.clone() { + Some(s) => s, + None => + return Ok(json!(compute_hex_encoded_return_error( + "identity_upload_idgraph is not avaiable" + ))), + }; + + match params.parse::() { + Ok(shard_base58) => { + let shard = match decode_shard_from_base58(shard_base58.as_str()) { + Ok(s) => s, + Err(msg) => { + let error_msg: String = + format!("Could not retrieve author_getNextNonce calls due to: {}", msg); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + + match local_state.load_cloned(&shard) { + Ok((mut state, _)) => { + + // TODO + }, + Err(e) => { + let error_msg = format!("load shard failure due to: {:?}", e); + Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + } + }, + Err(e) => { + let error_msg: String = + format!("Could not retrieve author_getNextNonce calls due to: {}", e); + Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + }); } #[deprecated(note = "`state_executeAesGetter` should be preferred")] diff --git a/tee-worker/identity/enclave-runtime/src/test/tests_main.rs b/tee-worker/identity/enclave-runtime/src/test/tests_main.rs index 0a61660650..0dacfbfce0 100644 --- a/tee-worker/identity/enclave-runtime/src/test/tests_main.rs +++ b/tee-worker/identity/enclave-runtime/src/test/tests_main.rs @@ -90,6 +90,8 @@ pub extern "C" fn test_main_entrance() -> size_t { itp_stf_state_handler::test::sgx_tests::test_list_state_ids_ignores_files_not_matching_the_pattern, itp_stf_state_handler::test::sgx_tests::test_in_memory_state_initializes_from_shard_directory, itp_sgx_crypto::tests::aes_sealing_works, + itp_sgx_crypto::tests::aes256_creating_repository_with_same_path_and_prefix_results_in_same_key, + itp_sgx_crypto::tests::aes256_creating_repository_with_same_path_and_prefix_but_new_key_results_in_new_key, itp_sgx_crypto::tests::using_get_aes_repository_twice_initializes_key_only_once, itp_sgx_crypto::tests::ed25529_sealing_works, itp_sgx_crypto::tests::using_get_ed25519_repository_twice_initializes_key_only_once, From b08e3a689ef0683cd94513b7886753222cac3020 Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Thu, 10 Oct 2024 08:17:43 +0000 Subject: [PATCH 03/13] small update --- parachain/pallets/omni-account/src/lib.rs | 15 +++++++++++++++ .../enclave-runtime/src/rpc/common_api.rs | 1 - 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index f2676ec01d..9ec1a2be76 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -311,6 +311,21 @@ pub mod pallet { Ok(()) } + + #[pallet::call_index(5)] + #[pallet::weight((195_000_000, DispatchClass::Normal))] + pub fn update_account_store_by_one( + origin: OriginFor, + owner_identity: Identity, + member_accounts: Vec, + ) -> DispatchResult { + let _ = T::TEECallOrigin::ensure_origin(origin)?; + let bounded_member_accounts: MemberAccounts = member_accounts + .try_into() + .map_err(|_| Error::::AccountStoreLenLimitReached)?; + + Ok(()) + } } impl Pallet { diff --git a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs index 5f1a99ca48..1d3755875c 100644 --- a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs +++ b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs @@ -532,7 +532,6 @@ pub fn add_common_api { - // TODO }, Err(e) => { From 5ac2aa21b898aedc422c4642d6ba992b1ee42f00 Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Tue, 15 Oct 2024 23:13:18 +0000 Subject: [PATCH 04/13] init --- common/primitives/core/src/lib.rs | 2 +- parachain/pallets/omni-account/src/lib.rs | 45 ++++--- tee-worker/Cargo.lock | 2 +- .../node-api/metadata/src/lib.rs | 12 +- .../node-api/metadata/src/metadata_mocks.rs | 37 +++++- .../metadata/src/pallet_omni_account.rs | 45 +++++++ .../core-primitives/sgx/crypto/src/aes256.rs | 2 +- .../common/litentry/primitives/src/lib.rs | 1 + .../identity/enclave-runtime/Cargo.lock | 2 + .../identity/enclave-runtime/Cargo.toml | 2 + .../src/initialization/global_components.rs | 4 +- .../enclave-runtime/src/initialization/mod.rs | 12 +- .../enclave-runtime/src/rpc/common_api.rs | 117 ++++++++++++++---- 13 files changed, 227 insertions(+), 56 deletions(-) create mode 100644 tee-worker/common/core-primitives/node-api/metadata/src/pallet_omni_account.rs diff --git a/common/primitives/core/src/lib.rs b/common/primitives/core/src/lib.rs index 647280f5c2..80e29894f0 100644 --- a/common/primitives/core/src/lib.rs +++ b/common/primitives/core/src/lib.rs @@ -32,7 +32,7 @@ pub use assertion::Assertion; pub mod identity; pub use identity::*; -mod omni_account; +pub mod omni_account; pub use omni_account::*; use alloc::{format, str, str::FromStr, string::String, vec, vec::Vec}; diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index a8a833b050..b33a43c8a7 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -55,7 +55,6 @@ pub enum RawOrigin { pub mod pallet { use super::*; - /// The current storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); #[pallet::pallet] @@ -133,6 +132,8 @@ pub mod pallet { AccountRemoved { who: T::AccountId, member_account_hashes: Vec }, /// Some member account is made public AccountMadePublic { who: T::AccountId, member_account_hash: H256 }, + /// An account store is updated + AccountStoreUpdated { who: T::AccountId }, /// Some call is dispatched as omni-account origin DispatchedAsOmniAccount { who: T::AccountId, result: DispatchResult }, /// Some call is dispatched as signed origin @@ -158,7 +159,7 @@ pub mod pallet { origin: OriginFor, member_account_hash: H256, call: Box<::RuntimeCall>, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; let omni_account = MemberAccountHash::::get(member_account_hash) .ok_or(Error::::AccountNotFound)?; @@ -167,7 +168,7 @@ pub mod pallet { who: omni_account, result: result.map(|_| ()).map_err(|e| e.error), }); - Ok(()) + Ok(Pays::No.into()) } // dispatch the `call` as the standard (frame_system) signed origin @@ -178,7 +179,7 @@ pub mod pallet { origin: OriginFor, member_account_hash: H256, call: Box<::RuntimeCall>, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; let omni_account = MemberAccountHash::::get(member_account_hash) .ok_or(Error::::AccountNotFound)?; @@ -190,12 +191,15 @@ pub mod pallet { who: omni_account, result: result.map(|_| ()).map_err(|e| e.error), }); - Ok(()) + Ok(Pays::No.into()) } #[pallet::call_index(2)] #[pallet::weight((195_000_000, DispatchClass::Normal))] - pub fn create_account_store(origin: OriginFor, identity: Identity) -> DispatchResult { + pub fn create_account_store( + origin: OriginFor, + identity: Identity, + ) -> DispatchResultWithPostInfo { // initial creation request has to come from `TEECallOrigin` let _ = T::TEECallOrigin::ensure_origin(origin)?; let hash = identity.hash(); @@ -217,7 +221,7 @@ pub mod pallet { account_store_hash: member_accounts.hash(), }); - Ok(()) + Ok(Pays::No.into()) } #[pallet::call_index(3)] @@ -307,19 +311,30 @@ pub mod pallet { Ok(()) } - #[pallet::call_index(5)] + /// "utitlity" extrinsic to upload the existing IDGraph from the worker onto chain + #[pallet::call_index(6)] #[pallet::weight((195_000_000, DispatchClass::Normal))] pub fn update_account_store_by_one( origin: OriginFor, - owner_identity: Identity, - member_accounts: Vec, - ) -> DispatchResult { + who: T::AccountId, + member_account: MemberAccount, + ) -> DispatchResultWithPostInfo { let _ = T::TEECallOrigin::ensure_origin(origin)?; - let bounded_member_accounts: MemberAccounts = member_accounts - .try_into() - .map_err(|_| Error::::AccountStoreLenLimitReached)?; - Ok(()) + let mut member_accounts = + AccountStore::::get(&who).ok_or(Error::::UnknownAccountStore)?; + + if !member_accounts.contains(&member_account) { + member_accounts + .try_push(member_account.clone()) + .map_err(|_| Error::::AccountStoreLenLimitReached)?; + } + + MemberAccountHash::::insert(member_account.hash(), who.clone()); + AccountStore::::insert(who.clone(), member_accounts); + Self::deposit_event(Event::AccountStoreUpdated { who }); + + Ok(Pays::No.into()) } } } diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index 73c14f8e0e..0923160723 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -4204,7 +4204,7 @@ dependencies = [ "sgx_tstd", "sgx_types", "sp-core", - "sp-std 5.0.0", + "sp-std", ] [[package]] diff --git a/tee-worker/common/core-primitives/node-api/metadata/src/lib.rs b/tee-worker/common/core-primitives/node-api/metadata/src/lib.rs index 352decf8ca..0362f47b5b 100644 --- a/tee-worker/common/core-primitives/node-api/metadata/src/lib.rs +++ b/tee-worker/common/core-primitives/node-api/metadata/src/lib.rs @@ -22,9 +22,10 @@ use crate::{ error::Result, pallet_balances::BalancesCallIndexes, pallet_bitacross::BitAcrossCallIndexes, pallet_evm_assertion::EvmAssertionsCallIndexes, pallet_imp::IMPCallIndexes, - pallet_proxy::ProxyCallIndexes, pallet_system::SystemConstants, - pallet_teebag::TeebagCallIndexes, pallet_timestamp::TimestampCallIndexes, - pallet_utility::UtilityCallIndexes, pallet_vcmp::VCMPCallIndexes, + pallet_omni_account::OmniAccountCallIndexes, pallet_proxy::ProxyCallIndexes, + pallet_system::SystemConstants, pallet_teebag::TeebagCallIndexes, + pallet_timestamp::TimestampCallIndexes, pallet_utility::UtilityCallIndexes, + pallet_vcmp::VCMPCallIndexes, }; use codec::{Decode, Encode}; use sp_core::storage::StorageKey; @@ -37,6 +38,7 @@ pub mod pallet_balances; pub mod pallet_bitacross; pub mod pallet_evm_assertion; pub mod pallet_imp; +pub mod pallet_omni_account; pub mod pallet_proxy; pub mod pallet_system; pub mod pallet_teebag; @@ -60,6 +62,7 @@ pub trait NodeMetadataTrait: + TimestampCallIndexes + EvmAssertionsCallIndexes + BitAcrossCallIndexes + + OmniAccountCallIndexes { } @@ -73,7 +76,8 @@ impl< + BalancesCallIndexes + TimestampCallIndexes + EvmAssertionsCallIndexes - + BitAcrossCallIndexes, + + BitAcrossCallIndexes + + OmniAccountCallIndexes, > NodeMetadataTrait for T { } diff --git a/tee-worker/common/core-primitives/node-api/metadata/src/metadata_mocks.rs b/tee-worker/common/core-primitives/node-api/metadata/src/metadata_mocks.rs index 6fb986da21..0189d1309d 100644 --- a/tee-worker/common/core-primitives/node-api/metadata/src/metadata_mocks.rs +++ b/tee-worker/common/core-primitives/node-api/metadata/src/metadata_mocks.rs @@ -18,9 +18,10 @@ use crate::{ error::Result, pallet_balances::BalancesCallIndexes, pallet_bitacross::BitAcrossCallIndexes, pallet_evm_assertion::EvmAssertionsCallIndexes, pallet_imp::IMPCallIndexes, - pallet_proxy::ProxyCallIndexes, pallet_system::SystemConstants, - pallet_teebag::TeebagCallIndexes, pallet_timestamp::TimestampCallIndexes, - pallet_utility::UtilityCallIndexes, pallet_vcmp::VCMPCallIndexes, runtime_call::RuntimeCall, + pallet_omni_account::OmniAccountCallIndexes, pallet_proxy::ProxyCallIndexes, + pallet_system::SystemConstants, pallet_teebag::TeebagCallIndexes, + pallet_timestamp::TimestampCallIndexes, pallet_utility::UtilityCallIndexes, + pallet_vcmp::VCMPCallIndexes, runtime_call::RuntimeCall, }; use codec::{Decode, Encode}; @@ -95,6 +96,12 @@ pub struct NodeMetadataMock { btc_wallet_generated: u8, eth_wallet_generated: u8, ton_wallet_generated: u8, + + omni_account_module: u8, + dispatch_as_omni_account: u8, + dispatch_as_signed: u8, + create_account_store: u8, + update_account_store_by_one: u8, } impl NodeMetadataMock { @@ -157,6 +164,12 @@ impl NodeMetadataMock { btc_wallet_generated: 2u8, eth_wallet_generated: 3u8, ton_wallet_generated: 4u8, + + omni_account_module: 70u8, + dispatch_as_omni_account: 0u8, + dispatch_as_signed: 1u8, + create_account_store: 2u8, + update_account_store_by_one: 3u8, } } } @@ -346,3 +359,21 @@ impl EvmAssertionsCallIndexes for NodeMetadataMock { Ok([self.evm_assertions_module, self.evm_assertions_void_assertion]) } } + +impl OmniAccountCallIndexes for NodeMetadataMock { + fn dispatch_as_omni_account_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.omni_account_module, self.dispatch_as_omni_account]) + } + + fn dispatch_as_signed_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.omni_account_module, self.dispatch_as_signed]) + } + + fn create_account_store_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.omni_account_module, self.create_account_store]) + } + + fn update_account_store_by_one_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.omni_account_module, self.update_account_store_by_one]) + } +} diff --git a/tee-worker/common/core-primitives/node-api/metadata/src/pallet_omni_account.rs b/tee-worker/common/core-primitives/node-api/metadata/src/pallet_omni_account.rs new file mode 100644 index 0000000000..cdd1101080 --- /dev/null +++ b/tee-worker/common/core-primitives/node-api/metadata/src/pallet_omni_account.rs @@ -0,0 +1,45 @@ +// 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 . + +// TODO: maybe use macros to simplify this +use crate::{error::Result, NodeMetadata}; + +const OMNIACCOUNT: &str = "OmniAccount"; + +pub trait OmniAccountCallIndexes { + fn dispatch_as_omni_account_call_indexes(&self) -> Result<[u8; 2]>; + fn dispatch_as_signed_call_indexes(&self) -> Result<[u8; 2]>; + fn create_account_store_call_indexes(&self) -> Result<[u8; 2]>; + fn update_account_store_by_one_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl OmniAccountCallIndexes for NodeMetadata { + fn dispatch_as_omni_account_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(OMNIACCOUNT, "dispatch_as_omni_account") + } + + fn dispatch_as_signed_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(OMNIACCOUNT, "dispatch_as_signed") + } + + fn create_account_store_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(OMNIACCOUNT, "create_account_store") + } + + fn update_account_store_by_one_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(OMNIACCOUNT, "update_account_store_by_one") + } +} diff --git a/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs b/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs index 64e2f2ac8a..11ecea9ae1 100644 --- a/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs +++ b/tee-worker/common/core-primitives/sgx/crypto/src/aes256.rs @@ -223,7 +223,7 @@ pub mod sgx { #[cfg(feature = "test")] pub mod sgx_tests { - use super::{sgx::*, *}; + use super::sgx::*; use crate::key_repository::AccessKey; use itp_sgx_temp_dir::TempDir; diff --git a/tee-worker/common/litentry/primitives/src/lib.rs b/tee-worker/common/litentry/primitives/src/lib.rs index e561fc2e67..07ea4cf198 100644 --- a/tee-worker/common/litentry/primitives/src/lib.rs +++ b/tee-worker/common/litentry/primitives/src/lib.rs @@ -71,6 +71,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/enclave-runtime/Cargo.lock b/tee-worker/identity/enclave-runtime/Cargo.lock index 2ba1b079b1..a37db32899 100644 --- a/tee-worker/identity/enclave-runtime/Cargo.lock +++ b/tee-worker/identity/enclave-runtime/Cargo.lock @@ -953,6 +953,7 @@ dependencies = [ "lc-evm-dynamic-assertions", "lc-identity-verification", "lc-parachain-extrinsic-task-receiver", + "lc-parachain-extrinsic-task-sender", "lc-stf-task-receiver", "lc-vc-task-receiver", "litentry-hex-utils", @@ -962,6 +963,7 @@ dependencies = [ "log", "multibase", "once_cell 1.4.0", + "pallet-identity-management-tee", "parity-scale-codec", "primitive-types", "rust-base58 0.0.4 (git+https://github.com/mesalock-linux/rust-base58-sgx?rev=sgx_1.1.3)", diff --git a/tee-worker/identity/enclave-runtime/Cargo.toml b/tee-worker/identity/enclave-runtime/Cargo.toml index 35b9c47107..4351319c56 100644 --- a/tee-worker/identity/enclave-runtime/Cargo.toml +++ b/tee-worker/identity/enclave-runtime/Cargo.toml @@ -148,12 +148,14 @@ lc-data-providers = { path = "../litentry/core/data-providers", default-features lc-evm-dynamic-assertions = { path = "../litentry/core/evm-dynamic-assertions", default-features = false, features = ["sgx"] } lc-identity-verification = { path = "../litentry/core/identity-verification", default-features = false, features = ["sgx"] } lc-parachain-extrinsic-task-receiver = { path = "../../common/litentry/core/parachain-extrinsic-task/receiver", default-features = false, features = ["sgx"] } +lc-parachain-extrinsic-task-sender = { path = "../../common/litentry/core/parachain-extrinsic-task/sender", default-features = false, features = ["sgx"] } lc-stf-task-receiver = { path = "../litentry/core/stf-task/receiver", default-features = false, features = ["sgx"] } lc-vc-task-receiver = { path = "../litentry/core/vc-task/receiver", default-features = false, features = ["sgx"] } litentry-hex-utils = { path = "../../../common/utils/hex", default-features = false } litentry-macros = { path = "../../../common/primitives/core/macros", default-features = false } litentry-primitives = { path = "../../common/litentry/primitives", default-features = false, features = ["sgx"] } litentry-proc-macros = { path = "../../../common/primitives/core/proc-macros", default-features = false } +pallet-identity-management-tee = { path = "../../common/litentry/pallets/identity-management", default-features = false } # substrate deps frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } diff --git a/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs b/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs index 9ec18fa8f6..846e134fa4 100644 --- a/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs +++ b/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs @@ -376,9 +376,9 @@ pub static GLOBAL_STATE_KEY_REPOSITORY_COMPONENT: ComponentContainer = ComponentContainer::new("IDGraph key repository"); +> = ComponentContainer::new("StoreAccount key repository"); /// Shielding key repository pub static GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT: ComponentContainer< diff --git a/tee-worker/identity/enclave-runtime/src/initialization/mod.rs b/tee-worker/identity/enclave-runtime/src/initialization/mod.rs index 904eb32f60..0a086913c6 100644 --- a/tee-worker/identity/enclave-runtime/src/initialization/mod.rs +++ b/tee-worker/identity/enclave-runtime/src/initialization/mod.rs @@ -26,9 +26,9 @@ use crate::{ EnclaveSidechainBlockSyncer, EnclaveStateFileIo, EnclaveStateHandler, EnclaveStateInitializer, EnclaveStateObserver, EnclaveStateSnapshotRepository, EnclaveStfEnclaveSigner, EnclaveTopPool, EnclaveTopPoolAuthor, - DIRECT_RPC_REQUEST_SINK_COMPONENT, GLOBAL_ASSERTION_REPOSITORY, - GLOBAL_ATTESTATION_HANDLER_COMPONENT, GLOBAL_DATA_PROVIDER_CONFIG, - GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT, GLOBAL_IDGRAPH_KEY_REPOSITORY_COMPONENT, + DIRECT_RPC_REQUEST_SINK_COMPONENT, GLOBAL_ACCOUNT_STORE_KEY_REPOSITORY_COMPONENT, + GLOBAL_ASSERTION_REPOSITORY, GLOBAL_ATTESTATION_HANDLER_COMPONENT, + GLOBAL_DATA_PROVIDER_CONFIG, GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT, GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_OCALL_API_COMPONENT, GLOBAL_RPC_WS_HANDLER_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT, GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT, @@ -115,9 +115,9 @@ pub(crate) fn init_enclave( let state_key_repository = Arc::new(get_aes_repository(base_dir.clone())?); GLOBAL_STATE_KEY_REPOSITORY_COMPONENT.initialize(state_key_repository.clone()); - let idgraph_key_repository = - Arc::new(create_aes256_repository(base_dir.clone(), "idgraph", None)?); - GLOBAL_IDGRAPH_KEY_REPOSITORY_COMPONENT.initialize(idgraph_key_repository.clone()); + let account_store_key_repository = + Arc::new(create_aes256_repository(base_dir.clone(), "account_store", None)?); + GLOBAL_ACCOUNT_STORE_KEY_REPOSITORY_COMPONENT.initialize(account_store_key_repository.clone()); let integritee_light_client_seal = Arc::new(EnclaveLightClientSeal::new( base_dir.join(LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH), diff --git a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs index 55b7a3072f..699ca95c32 100644 --- a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs +++ b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs @@ -3,8 +3,12 @@ use crate::{ generate_dcap_ra_extrinsic_from_quote_internal, generate_ias_ra_extrinsic_from_der_cert_internal, }, + initialization::global_components::GLOBAL_ACCOUNT_STORE_KEY_REPOSITORY_COMPONENT, std::borrow::ToOwned, - utils::get_validator_accessor_from_integritee_solo_or_parachain, + utils::{ + get_node_metadata_repository_from_integritee_solo_or_parachain, + get_validator_accessor_from_integritee_solo_or_parachain, + }, }; use base58::FromBase58; use codec::{Decode, Encode}; @@ -12,6 +16,10 @@ use core::result::Result; use ita_sgx_runtime::{Runtime, System, VERSION}; use ita_stf::{aes_encrypt_default, AesOutput, Getter, TrustedCallSigned}; use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, ExtrinsicSender}; +use itp_component_container::ComponentGetter; +use itp_node_api::metadata::{ + pallet_omni_account::OmniAccountCallIndexes, provider::AccessNodeMetadata, NodeMetadata, +}; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_primitives_cache::{GetPrimitives, GLOBAL_PRIMITIVES_CACHE}; use itp_rpc::RpcReturnValue; @@ -24,14 +32,15 @@ use itp_sgx_externalities::SgxExternalitiesTrait; use itp_stf_executor::getter_executor::ExecuteGetter; use itp_stf_state_handler::handle_state::HandleState; use itp_top_pool_author::traits::AuthorApi; -use itp_types::{DirectRequestStatus, Index, RsaRequest, ShardIdentifier, H256}; +use itp_types::{DirectRequestStatus, Index, OpaqueCall, RsaRequest, ShardIdentifier, H256}; use itp_utils::{FromHexPrefixed, ToHexPrefixed}; use its_rpc_handler::direct_top_pool_api::add_top_pool_direct_rpc_methods; use jsonrpc_core::{serde_json::json, IoHandler, Params, Value}; use lc_data_providers::DataProviderConfig; use lc_identity_verification::web2::{email, twitter}; -use litentry_macros::{if_development, if_development_or}; -use litentry_primitives::{aes_decrypt, AesRequest, DecryptableRequest, Identity}; +use lc_parachain_extrinsic_task_sender::{ParachainExtrinsicSender, SendParachainExtrinsic}; +use litentry_macros::if_development; +use litentry_primitives::{aes_decrypt, AesRequest, DecryptableRequest, Identity, MemberAccount}; use log::debug; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::Pair; @@ -113,7 +122,7 @@ pub fn add_common_api s, None => return Ok(json!(compute_hex_encoded_return_error( @@ -507,15 +517,15 @@ pub fn add_common_api s, None => return Ok(json!(compute_hex_encoded_return_error( - "identity_upload_idgraph is not avaiable" + "omni_uploadAccountStore is not avaiable" ))), }; @@ -530,22 +540,83 @@ pub fn add_common_api { - // TODO - }, - Err(e) => { - let error_msg = format!("load shard failure due to: {:?}", e); - Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + let aes_key = + match GLOBAL_ACCOUNT_STORE_KEY_REPOSITORY_COMPONENT.get().and_then(|r| { + r.retrieve_key() + .map_err(|_| itp_component_container::error::Error::Other("".into())) + }) { + Ok(k) => k, + Err(e) => { + let error_msg = + format!("Cannot get AccountStore key repository: {:?}", e); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + + let node_metadata_repo = + match get_node_metadata_repository_from_integritee_solo_or_parachain() { + Ok(r) => r, + Err(e) => + return Ok(json!(compute_hex_encoded_return_error( + format!("{:?}", e).as_str() + ))), + }; + + let call_index = match node_metadata_repo + .get_from_metadata(|m| m.update_account_store_by_one_call_indexes()) + { + Ok(r) => match r { + Ok(r) => r, + Err(e) => + return Ok(json!(compute_hex_encoded_return_error( + format!("{:?}", e).as_str() + ))), }, + Err(e) => + return Ok(json!(compute_hex_encoded_return_error( + format!("{:?}", e).as_str() + ))), + }; + + let identities: Vec<(Identity, Identity)> = match local_state.load_cloned(&shard) { + Ok((mut state, _)) => state.execute_with(|| { + pallet_identity_management_tee::IDGraphs::::iter_keys().collect() + }), + Err(e) => + return Ok(json!(compute_hex_encoded_return_error( + format!("{:?}", e).as_str() + ))), + }; + + let sender = ParachainExtrinsicSender::new(); + + for (prime_id, sub_id) in identities { + let member_account: MemberAccount = if prime_id == sub_id { + sub_id.into() + } else { + let enc_id: Vec = sub_id.encode(); + MemberAccount::Private( + aes_encrypt_default(&aes_key, &enc_id).encode(), + sub_id.hash(), + ) + }; + + let call = OpaqueCall::from_tuple(&( + call_index, + prime_id.to_omni_account(), + member_account, + )); + + if let Err(e) = sender.send(call) { + return Ok(json!(compute_hex_encoded_return_error(e.as_str()))) + } } + + let json_value = RpcReturnValue::new(vec![], false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) }, - Err(e) => { - let error_msg: String = - format!("Could not retrieve author_getNextNonce calls due to: {}", e); - Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - }; + Err(_) => Ok(json!(compute_hex_encoded_return_error("Could not parse params"))), + } }); } From 6724c09b787efa76f12ca7c17a8216fd3211e471 Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Wed, 16 Oct 2024 07:57:55 +0000 Subject: [PATCH 05/13] add cli --- .../cli/src/base_cli/commands/litentry/mod.rs | 22 +++++++--- .../commands/litentry/upload_id_graph.rs | 43 +++++++++++++++++++ tee-worker/identity/cli/src/base_cli/mod.rs | 16 +++---- .../enclave-runtime/src/rpc/common_api.rs | 6 +-- 4 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 tee-worker/identity/cli/src/base_cli/commands/litentry/upload_id_graph.rs diff --git a/tee-worker/identity/cli/src/base_cli/commands/litentry/mod.rs b/tee-worker/identity/cli/src/base_cli/commands/litentry/mod.rs index baefc8c487..3981f000bc 100644 --- a/tee-worker/identity/cli/src/base_cli/commands/litentry/mod.rs +++ b/tee-worker/identity/cli/src/base_cli/commands/litentry/mod.rs @@ -14,10 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -pub mod activate_identity; -pub mod deactivate_identity; -pub mod id_graph_hash; -pub mod link_identity; -pub mod shield_text; +mod activate_identity; +pub use activate_identity::*; + +mod deactivate_identity; +pub use deactivate_identity::*; + +mod id_graph_hash; +pub use id_graph_hash::*; + +mod link_identity; +pub use link_identity::*; + +mod shield_text; +pub use shield_text::*; + +mod upload_id_graph; +pub use upload_id_graph::*; pub const IMP: &str = "IdentityManagement"; diff --git a/tee-worker/identity/cli/src/base_cli/commands/litentry/upload_id_graph.rs b/tee-worker/identity/cli/src/base_cli/commands/litentry/upload_id_graph.rs new file mode 100644 index 0000000000..02d629863d --- /dev/null +++ b/tee-worker/identity/cli/src/base_cli/commands/litentry/upload_id_graph.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 . + +use crate::{command_utils::get_worker_api_direct, Cli, CliResult, CliResultOk}; +use base58::ToBase58; +use codec::{Decode, Encode}; +use itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{Id, RpcRequest}; +use itp_types::ShardIdentifier; + +// usage: ./bin/litentry-cli upload-id-graph + +#[derive(Parser)] +pub struct UploadIdGraphCommand; +impl UploadIdGraphCommand { + pub(crate) fn run(&self, cli: &Cli) -> CliResult { + let direct_api = get_worker_api_direct(cli); + let mrenclave = direct_api.get_state_mrenclave().unwrap(); + let shard = ShardIdentifier::decode(&mut &mrenclave[..]).unwrap(); + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "omni_UploadIDGraph".to_owned(), + vec![shard.encode().to_base58()], + ) + .unwrap(); + + let _ = direct_api.get(&jsonrpc_call).unwrap(); + Ok(CliResultOk::None) + } +} diff --git a/tee-worker/identity/cli/src/base_cli/mod.rs b/tee-worker/identity/cli/src/base_cli/mod.rs index 0d4fda7fea..0ac4aa6291 100644 --- a/tee-worker/identity/cli/src/base_cli/mod.rs +++ b/tee-worker/identity/cli/src/base_cli/mod.rs @@ -17,16 +17,8 @@ use crate::{ base_cli::commands::{ - balance::BalanceCommand, - faucet::FaucetCommand, - listen::ListenCommand, - litentry::{ - activate_identity::ActivateIdentityCommand, - deactivate_identity::DeactivateIdentityCommand, id_graph_hash::IDGraphHashCommand, - link_identity::LinkIdentityCommand, shield_text::ShieldTextCommand, - }, - register_tcb_info::RegisterTcbInfoCommand, - transfer::TransferCommand, + balance::BalanceCommand, faucet::FaucetCommand, listen::ListenCommand, litentry::*, + register_tcb_info::RegisterTcbInfoCommand, transfer::TransferCommand, }, command_utils::*, Cli, CliResult, CliResultOk, ED25519_KEY_TYPE, SR25519_KEY_TYPE, @@ -99,6 +91,9 @@ pub enum BaseCommand { /// Shield text ShieldText(ShieldTextCommand), + + /// Upload the IDGraph onto chain as AccountStore + UploadIdGraph(UploadIdGraphCommand), } impl BaseCommand { @@ -121,6 +116,7 @@ impl BaseCommand { BaseCommand::DeactivateIdentity(cmd) => cmd.run(cli), BaseCommand::ActivateIdentity(cmd) => cmd.run(cli), BaseCommand::ShieldText(cmd) => cmd.run(cli), + BaseCommand::UploadIdGraph(cmd) => cmd.run(cli), } } } diff --git a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs index 699ca95c32..270588a906 100644 --- a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs +++ b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs @@ -519,13 +519,13 @@ pub fn add_common_api s, None => return Ok(json!(compute_hex_encoded_return_error( - "omni_uploadAccountStore is not avaiable" + "omni_UploadIDGraph is not avaiable" ))), }; From e6a50e45d757e42ae91412a2cd72bd3a9a76283b Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Wed, 16 Oct 2024 11:55:40 +0000 Subject: [PATCH 06/13] fix param parsing --- parachain/pallets/omni-account/src/lib.rs | 63 +++++++++++-------- .../enclave-runtime/src/rpc/common_api.rs | 9 +-- 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index b33a43c8a7..3e0ca63101 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -202,25 +202,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { // initial creation request has to come from `TEECallOrigin` let _ = T::TEECallOrigin::ensure_origin(origin)?; - let hash = identity.hash(); - let omni_account = T::OmniAccountConverter::convert(&identity); - - ensure!(!MemberAccountHash::::contains_key(hash), Error::::AccountAlreadyAdded); - - let mut member_accounts: MemberAccounts = BoundedVec::new(); - member_accounts - .try_push(identity.into()) - .map_err(|_| Error::::AccountStoreLenLimitReached)?; - - MemberAccountHash::::insert(hash, omni_account.clone()); - AccountStore::::insert(omni_account.clone(), member_accounts.clone()); - AccountStoreHash::::insert(omni_account.clone(), member_accounts.hash()); - - Self::deposit_event(Event::AccountStoreCreated { - who: omni_account, - account_store_hash: member_accounts.hash(), - }); - + let _ = Self::do_create_account_store(identity)?; Ok(Pays::No.into()) } @@ -316,13 +298,17 @@ pub mod pallet { #[pallet::weight((195_000_000, DispatchClass::Normal))] pub fn update_account_store_by_one( origin: OriginFor, - who: T::AccountId, + who: Identity, member_account: MemberAccount, ) -> DispatchResultWithPostInfo { - let _ = T::TEECallOrigin::ensure_origin(origin)?; + let _ = T::TEECallOrigin::ensure_origin(origin.clone())?; - let mut member_accounts = - AccountStore::::get(&who).ok_or(Error::::UnknownAccountStore)?; + let who_account = T::OmniAccountConverter::convert(&who); + + let mut member_accounts = match AccountStore::::get(&who_account) { + Some(s) => s, + None => Self::do_create_account_store(who)?, + }; if !member_accounts.contains(&member_account) { member_accounts @@ -330,13 +316,38 @@ pub mod pallet { .map_err(|_| Error::::AccountStoreLenLimitReached)?; } - MemberAccountHash::::insert(member_account.hash(), who.clone()); - AccountStore::::insert(who.clone(), member_accounts); - Self::deposit_event(Event::AccountStoreUpdated { who }); + MemberAccountHash::::insert(member_account.hash(), who_account.clone()); + AccountStore::::insert(who_account.clone(), member_accounts); + Self::deposit_event(Event::AccountStoreUpdated { who: who_account }); Ok(Pays::No.into()) } } + + impl Pallet { + fn do_create_account_store(identity: Identity) -> Result, Error> { + let hash = identity.hash(); + let omni_account = T::OmniAccountConverter::convert(&identity); + + ensure!(!MemberAccountHash::::contains_key(hash), Error::::AccountAlreadyAdded); + + let mut member_accounts: MemberAccounts = BoundedVec::new(); + member_accounts + .try_push(identity.into()) + .map_err(|_| Error::::AccountStoreLenLimitReached)?; + + MemberAccountHash::::insert(hash, omni_account.clone()); + AccountStore::::insert(omni_account.clone(), member_accounts.clone()); + AccountStoreHash::::insert(omni_account.clone(), member_accounts.hash()); + + Self::deposit_event(Event::AccountStoreCreated { + who: omni_account, + account_store_hash: member_accounts.hash(), + }); + + Ok(member_accounts) + } + } } pub struct EnsureOmniAccount(PhantomData); diff --git a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs index 270588a906..4a5182dcaa 100644 --- a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs +++ b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs @@ -18,7 +18,7 @@ use ita_stf::{aes_encrypt_default, AesOutput, Getter, TrustedCallSigned}; use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, ExtrinsicSender}; use itp_component_container::ComponentGetter; use itp_node_api::metadata::{ - pallet_omni_account::OmniAccountCallIndexes, provider::AccessNodeMetadata, NodeMetadata, + pallet_omni_account::OmniAccountCallIndexes, provider::AccessNodeMetadata, }; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_primitives_cache::{GetPrimitives, GLOBAL_PRIMITIVES_CACHE}; @@ -41,7 +41,7 @@ use lc_identity_verification::web2::{email, twitter}; use lc_parachain_extrinsic_task_sender::{ParachainExtrinsicSender, SendParachainExtrinsic}; use litentry_macros::if_development; use litentry_primitives::{aes_decrypt, AesRequest, DecryptableRequest, Identity, MemberAccount}; -use log::debug; +use log::*; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::Pair; use sp_runtime::OpaqueExtrinsic; @@ -529,8 +529,8 @@ pub fn add_common_api() { - Ok(shard_base58) => { + match params.parse::<(String,)>() { + Ok((shard_base58,)) => { let shard = match decode_shard_from_base58(shard_base58.as_str()) { Ok(s) => s, Err(msg) => { @@ -589,6 +589,7 @@ pub fn add_common_api Date: Wed, 16 Oct 2024 11:57:10 +0000 Subject: [PATCH 07/13] update lockfile --- tee-worker/bitacross/enclave-runtime/Cargo.lock | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tee-worker/bitacross/enclave-runtime/Cargo.lock b/tee-worker/bitacross/enclave-runtime/Cargo.lock index 658c651b7c..214b27c9db 100644 --- a/tee-worker/bitacross/enclave-runtime/Cargo.lock +++ b/tee-worker/bitacross/enclave-runtime/Cargo.lock @@ -988,7 +988,6 @@ dependencies = [ "serde 1.0.204", "serde_json 1.0.120", "sp-core", - "sp-core-hashing", "sp-io", "sp-runtime", "sp-std", @@ -2560,7 +2559,7 @@ dependencies = [ "frame-support", "hash-db 0.15.2", "itp-types", - "litentry-hex-utils 0.1.0", + "litentry-hex-utils", "parity-scale-codec", "sgx_tstd", "sp-core", From 1a40f8d3a39d8808bff3106aed789fed94f7bebc Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Wed, 16 Oct 2024 12:26:55 +0000 Subject: [PATCH 08/13] fix bug --- tee-worker/identity/enclave-runtime/src/rpc/common_api.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs index 4a5182dcaa..6e0c56b15a 100644 --- a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs +++ b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs @@ -602,11 +602,7 @@ pub fn add_common_api Date: Thu, 17 Oct 2024 08:52:03 +0000 Subject: [PATCH 09/13] use subcommand --- .../src/initialization/global_components.rs | 2 +- .../enclave-api/ffi/src/lib.rs | 2 + .../enclave-api/src/enclave_base.rs | 13 +++ .../identity/enclave-runtime/Enclave.edl | 2 + .../src/initialization/global_components.rs | 4 +- .../enclave-runtime/src/initialization/mod.rs | 88 ++++++++++++++++++- .../identity/enclave-runtime/src/lib.rs | 10 +++ tee-worker/identity/service/src/cli.yml | 9 +- tee-worker/identity/service/src/main_impl.rs | 8 ++ .../src/tests/mocks/enclave_api_mock.rs | 4 + 10 files changed, 134 insertions(+), 8 deletions(-) diff --git a/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs b/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs index d64c580aaa..6e60d93af5 100644 --- a/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs +++ b/tee-worker/bitacross/enclave-runtime/src/initialization/global_components.rs @@ -68,7 +68,7 @@ use itp_sgx_crypto::{ ecdsa::{Pair as EcdsaPair, Seal as EcdsaSeal}, key_repository::KeyRepository, schnorr::{Pair as SchnorrPair, Seal as SchnorrSeal}, - Aes, AesSeal, Ed25519Seal, IDGraphKey, IDGraphKeySeal, Rsa3072Seal, + Aes, AesSeal, Ed25519Seal, Rsa3072Seal, }; use itp_stf_executor::{ enclave_signer::StfEnclaveSigner, executor::StfExecutor, getter_executor::GetterExecutor, diff --git a/tee-worker/identity/core-primitives/enclave-api/ffi/src/lib.rs b/tee-worker/identity/core-primitives/enclave-api/ffi/src/lib.rs index 65b1b11aa1..cf755efcc1 100644 --- a/tee-worker/identity/core-primitives/enclave-api/ffi/src/lib.rs +++ b/tee-worker/identity/core-primitives/enclave-api/ffi/src/lib.rs @@ -238,6 +238,8 @@ extern "C" { shard_size: u32, ) -> sgx_status_t; + pub fn upload_id_graph(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t; + pub fn ignore_parentchain_block_import_validation_until( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, diff --git a/tee-worker/identity/core-primitives/enclave-api/src/enclave_base.rs b/tee-worker/identity/core-primitives/enclave-api/src/enclave_base.rs index 47f0bfa08f..69e8a0c9eb 100644 --- a/tee-worker/identity/core-primitives/enclave-api/src/enclave_base.rs +++ b/tee-worker/identity/core-primitives/enclave-api/src/enclave_base.rs @@ -82,6 +82,8 @@ pub trait EnclaveBase: Send + Sync + 'static { // litentry fn migrate_shard(&self, new_shard: Vec) -> EnclaveResult<()>; + + fn upload_id_graph(&self) -> EnclaveResult<()>; } /// EnclaveApi implementation for Enclave struct @@ -388,6 +390,17 @@ mod impl_ffi { Ok(()) } + + fn upload_id_graph(&self) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { ffi::upload_id_graph(self.eid, &mut retval) }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } } fn init_parentchain_components_ffi( diff --git a/tee-worker/identity/enclave-runtime/Enclave.edl b/tee-worker/identity/enclave-runtime/Enclave.edl index 3e4a13e34f..94c1be5f1c 100644 --- a/tee-worker/identity/enclave-runtime/Enclave.edl +++ b/tee-worker/identity/enclave-runtime/Enclave.edl @@ -170,6 +170,8 @@ enclave { uint32_t shard_size ); + public sgx_status_t upload_id_graph(); + public sgx_status_t ignore_parentchain_block_import_validation_until( [in] uint32_t* until ); diff --git a/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs b/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs index 846e134fa4..e72d54b425 100644 --- a/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs +++ b/tee-worker/identity/enclave-runtime/src/initialization/global_components.rs @@ -109,7 +109,7 @@ pub type EnclaveGetter = Getter; pub type EnclaveTrustedCallSigned = TrustedCallSigned; pub type EnclaveStf = Stf; pub type EnclaveStateKeyRepository = KeyRepository; -pub type EnclaveIDGraphKeyRepository = KeyRepository; +pub type EnclaveAccountStoreKeyRepository = KeyRepository; pub type EnclaveShieldingKeyRepository = KeyRepository; pub type EnclaveSigningKeyRepository = KeyRepository; pub type EnclaveStateFileIo = SgxStateFileIo; @@ -377,7 +377,7 @@ pub static GLOBAL_STATE_KEY_REPOSITORY_COMPONENT: ComponentContainer = ComponentContainer::new("StoreAccount key repository"); /// Shielding key repository diff --git a/tee-worker/identity/enclave-runtime/src/initialization/mod.rs b/tee-worker/identity/enclave-runtime/src/initialization/mod.rs index 53ed6d42ec..252e8b9b28 100644 --- a/tee-worker/identity/enclave-runtime/src/initialization/mod.rs +++ b/tee-worker/identity/enclave-runtime/src/initialization/mod.rs @@ -52,7 +52,8 @@ use crate::{ use base58::ToBase58; use codec::Encode; use core::str::FromStr; -use ita_stf::{Getter, TrustedCallSigned}; +use ita_sgx_runtime::Runtime; +use ita_stf::{aes_encrypt_default, Getter, TrustedCallSigned}; use itc_direct_rpc_server::{ create_determine_watch, rpc_connection_registry::ConnectionRegistry, rpc_ws_handler::RpcWsHandler, @@ -65,6 +66,11 @@ use itc_tls_websocket_server::{ }; use itp_attestation_handler::IntelAttestationHandler; use itp_component_container::{ComponentGetter, ComponentInitializer}; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_node_api::metadata::{ + pallet_omni_account::OmniAccountCallIndexes, provider::AccessNodeMetadata, +}; +use itp_ocall_api::EnclaveOnChainOCallApi; use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE; use itp_settings::files::{ ASSERTIONS_FILE, LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE, @@ -73,6 +79,7 @@ use itp_settings::files::{ use itp_sgx_crypto::{ get_aes_repository, get_ed25519_repository, get_rsa3072_repository, key_repository::AccessKey, }; +use itp_sgx_externalities::SgxExternalitiesTrait; use itp_stf_state_handler::{ file_io::StateDir, handle_state::HandleState, query_shard_state::QueryShardState, state_snapshot_repository::VersionedStateAccess, @@ -80,7 +87,7 @@ use itp_stf_state_handler::{ }; use itp_top_pool::pool::Options as PoolOptions; use itp_top_pool_author::author::{AuthorTopFilter, BroadcastedTopFilter}; -use itp_types::{parentchain::ParentchainId, ShardIdentifier}; +use itp_types::{parentchain::ParentchainId, OpaqueCall, ShardIdentifier}; use its_sidechain::{ block_composer::BlockComposer, slots::{FailSlotMode, FailSlotOnDemand}, @@ -92,11 +99,13 @@ use lc_native_task_receiver::{run_native_task_receiver, NativeTaskContext}; use lc_parachain_extrinsic_task_receiver::run_parachain_extrinsic_task_receiver; use lc_stf_task_receiver::{run_stf_task_receiver, StfTaskContext}; use lc_vc_task_receiver::run_vc_handler_runner; -use litentry_primitives::{sgx::create_aes256_repository, BroadcastedRequest}; +use litentry_primitives::{ + sgx::create_aes256_repository, BroadcastedRequest, Identity, MemberAccount, +}; use log::*; use sgx_types::sgx_status_t; use sp_core::crypto::Pair; -use std::{collections::HashMap, path::PathBuf, string::String, sync::Arc}; +use std::{collections::HashMap, path::PathBuf, string::String, sync::Arc, vec::Vec}; pub(crate) fn init_enclave( mu_ra_url: String, @@ -514,6 +523,77 @@ pub(crate) fn migrate_shard(new_shard: ShardIdentifier) -> EnclaveResult<()> { Ok(()) } +pub(crate) fn upload_id_graph() -> EnclaveResult<()> { + const BATCH_SIZE: usize = 400; + + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let extrinsic_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + + let aes_key = GLOBAL_ACCOUNT_STORE_KEY_REPOSITORY_COMPONENT + .get() + .and_then(|r| { + r.retrieve_key() + .map_err(|_| itp_component_container::error::Error::Other("".into())) + }) + .map_err(|e| Error::Other(e.into()))?; + + let call_index = node_metadata_repo + .get_from_metadata(|m| m.update_account_store_by_one_call_indexes())??; + + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + + let shard = match state_handler.list_shards()? { + shards if shards.len() == 1 => shards[0], + _ => return Err(Error::Other("Cannot get shard".into())), + }; + + let identities: Vec<(Identity, Identity)> = match state_handler.load_cloned(&shard) { + Ok((mut state, _)) => state.execute_with(|| { + pallet_identity_management_tee::IDGraphs::::iter_keys().collect() + }), + Err(e) => return Err(Error::Other(e.into())), + }; + + info!("uploading {} identity pairs", identities.len()); + + let mut calls: Vec = Default::default(); + for (prime_id, sub_id) in identities { + let member_account: MemberAccount = if prime_id == sub_id { + sub_id.into() + } else { + let enc_id: Vec = sub_id.encode(); + MemberAccount::Private(aes_encrypt_default(&aes_key, &enc_id).encode(), sub_id.hash()) + }; + + let call = OpaqueCall::from_tuple(&(call_index, prime_id, member_account)); + calls.push(call); + + if calls.len() >= BATCH_SIZE { + let _ = extrinsic_factory + .create_batch_extrinsic(calls.drain(..).collect(), None) + .map_err(|_| Error::Other("failed to create extrinsic".into())) + .and_then(|ext| { + ocall_api + .send_to_parentchain(vec![ext], &ParentchainId::Litentry, true) + .map_err(|_| Error::Other("failed to send extrinsic".into())) + })?; + } + } + + if !calls.is_empty() { + let _ = extrinsic_factory + .create_batch_extrinsic(calls.drain(..).collect(), None) + .map_err(|_| Error::Other("failed to create extrinsic".into())) + .and_then(|ext| { + ocall_api + .send_to_parentchain(vec![ext], &ParentchainId::Litentry, true) + .map_err(|_| Error::Other("failed to send extrinsic".into())) + })?; + } + Ok(()) +} + /// Initialize the TOP pool author component. pub fn create_top_pool_author( rpc_responder: Arc, diff --git a/tee-worker/identity/enclave-runtime/src/lib.rs b/tee-worker/identity/enclave-runtime/src/lib.rs index 9531f372da..eec659a6b3 100644 --- a/tee-worker/identity/enclave-runtime/src/lib.rs +++ b/tee-worker/identity/enclave-runtime/src/lib.rs @@ -440,6 +440,16 @@ pub unsafe extern "C" fn migrate_shard(new_shard: *const u8, shard_size: u32) -> sgx_status_t::SGX_SUCCESS } +#[no_mangle] +pub unsafe extern "C" fn upload_id_graph() -> sgx_status_t { + if let Err(e) = initialization::upload_id_graph() { + error!("Failed to upload IDGraph: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + + sgx_status_t::SGX_SUCCESS +} + #[no_mangle] pub unsafe extern "C" fn sync_parentchain( blocks_to_sync: *const u8, diff --git a/tee-worker/identity/service/src/cli.yml b/tee-worker/identity/service/src/cli.yml index 2b33dd20a5..9d31cf53a2 100644 --- a/tee-worker/identity/service/src/cli.yml +++ b/tee-worker/identity/service/src/cli.yml @@ -176,7 +176,7 @@ subcommands: - mrenclave: about: Dump mrenclave to stdout. base58 encoded. - init-shard: - about: Initialize new shard (do this only if you run the first worker for that shard). if shard is not specified, the MRENCLAVE is used instead + about: Initialize new shard (do this only if you run the first worker for that shard). Default is mrenclave args: - shard: required: false @@ -185,6 +185,13 @@ subcommands: help: shard identifier base58 encoded - migrate-shard: about: Migrate state from old shards to the new(current) shard, which is identical to mrenclave + - upload-id-graph: + about: Upload the existing IDGraph in the sidechain state onto parachain + args: + - shard: + long: shard + required: false + help: shard identifier base58 encoded. Defines the state that this worker shall operate on. Default is mrenclave - test: about: Run tests involving the enclave takes_value: true diff --git a/tee-worker/identity/service/src/main_impl.rs b/tee-worker/identity/service/src/main_impl.rs index 137e0e90f8..e5f9c0dcc4 100644 --- a/tee-worker/identity/service/src/main_impl.rs +++ b/tee-worker/identity/service/src/main_impl.rs @@ -291,6 +291,14 @@ pub(crate) fn main() { setup::migrate_shard(enclave.as_ref(), &new_shard); let new_shard_name = new_shard.encode().to_base58(); setup::remove_old_shards(config.data_dir(), &new_shard_name); + } else if let Some(sub_matches) = matches.subcommand_matches("upload-id-graph") { + let tee_accountid = enclave_account(enclave.as_ref()); + let shard = extract_shard(sub_matches.value_of("shard"), enclave.as_ref()); + info!("shard is {:?}", shard); + let node_api = + node_api_factory.create_api().expect("Failed to create parentchain node API"); + init_parentchain(&enclave, &node_api, &tee_accountid, ParentchainId::Litentry, &shard); + enclave.upload_id_graph(); } else { info!("For options: use --help"); } diff --git a/tee-worker/identity/service/src/tests/mocks/enclave_api_mock.rs b/tee-worker/identity/service/src/tests/mocks/enclave_api_mock.rs index fc194e4f63..ef500df115 100644 --- a/tee-worker/identity/service/src/tests/mocks/enclave_api_mock.rs +++ b/tee-worker/identity/service/src/tests/mocks/enclave_api_mock.rs @@ -103,6 +103,10 @@ impl EnclaveBase for EnclaveMock { fn migrate_shard(&self, new_shard: Vec) -> EnclaveResult<()> { unimplemented!() } + + fn upload_id_graph(&self) -> EnclaveResult<()> { + unimplemented!() + } } impl Sidechain for EnclaveMock { From 7080748c166293941ada2dd592c2749eefd0cd2e Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Thu, 17 Oct 2024 08:56:03 +0000 Subject: [PATCH 10/13] remove rpc --- .../cli/src/base_cli/commands/litentry/mod.rs | 3 - .../commands/litentry/upload_id_graph.rs | 43 ------- tee-worker/identity/cli/src/base_cli/mod.rs | 4 - .../enclave-runtime/src/rpc/common_api.rs | 114 +----------------- 4 files changed, 3 insertions(+), 161 deletions(-) delete mode 100644 tee-worker/identity/cli/src/base_cli/commands/litentry/upload_id_graph.rs diff --git a/tee-worker/identity/cli/src/base_cli/commands/litentry/mod.rs b/tee-worker/identity/cli/src/base_cli/commands/litentry/mod.rs index 3981f000bc..1d40f69ec2 100644 --- a/tee-worker/identity/cli/src/base_cli/commands/litentry/mod.rs +++ b/tee-worker/identity/cli/src/base_cli/commands/litentry/mod.rs @@ -29,7 +29,4 @@ pub use link_identity::*; mod shield_text; pub use shield_text::*; -mod upload_id_graph; -pub use upload_id_graph::*; - pub const IMP: &str = "IdentityManagement"; diff --git a/tee-worker/identity/cli/src/base_cli/commands/litentry/upload_id_graph.rs b/tee-worker/identity/cli/src/base_cli/commands/litentry/upload_id_graph.rs deleted file mode 100644 index 02d629863d..0000000000 --- a/tee-worker/identity/cli/src/base_cli/commands/litentry/upload_id_graph.rs +++ /dev/null @@ -1,43 +0,0 @@ -// 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::{command_utils::get_worker_api_direct, Cli, CliResult, CliResultOk}; -use base58::ToBase58; -use codec::{Decode, Encode}; -use itc_rpc_client::direct_client::DirectApi; -use itp_rpc::{Id, RpcRequest}; -use itp_types::ShardIdentifier; - -// usage: ./bin/litentry-cli upload-id-graph - -#[derive(Parser)] -pub struct UploadIdGraphCommand; -impl UploadIdGraphCommand { - pub(crate) fn run(&self, cli: &Cli) -> CliResult { - let direct_api = get_worker_api_direct(cli); - let mrenclave = direct_api.get_state_mrenclave().unwrap(); - let shard = ShardIdentifier::decode(&mut &mrenclave[..]).unwrap(); - let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( - Id::Text("1".to_string()), - "omni_UploadIDGraph".to_owned(), - vec![shard.encode().to_base58()], - ) - .unwrap(); - - let _ = direct_api.get(&jsonrpc_call).unwrap(); - Ok(CliResultOk::None) - } -} diff --git a/tee-worker/identity/cli/src/base_cli/mod.rs b/tee-worker/identity/cli/src/base_cli/mod.rs index 0ac4aa6291..385b7f967a 100644 --- a/tee-worker/identity/cli/src/base_cli/mod.rs +++ b/tee-worker/identity/cli/src/base_cli/mod.rs @@ -91,9 +91,6 @@ pub enum BaseCommand { /// Shield text ShieldText(ShieldTextCommand), - - /// Upload the IDGraph onto chain as AccountStore - UploadIdGraph(UploadIdGraphCommand), } impl BaseCommand { @@ -116,7 +113,6 @@ impl BaseCommand { BaseCommand::DeactivateIdentity(cmd) => cmd.run(cli), BaseCommand::ActivateIdentity(cmd) => cmd.run(cli), BaseCommand::ShieldText(cmd) => cmd.run(cli), - BaseCommand::UploadIdGraph(cmd) => cmd.run(cli), } } } diff --git a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs index 6e0c56b15a..49e1289f42 100644 --- a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs +++ b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs @@ -3,12 +3,8 @@ use crate::{ generate_dcap_ra_extrinsic_from_quote_internal, generate_ias_ra_extrinsic_from_der_cert_internal, }, - initialization::global_components::GLOBAL_ACCOUNT_STORE_KEY_REPOSITORY_COMPONENT, std::borrow::ToOwned, - utils::{ - get_node_metadata_repository_from_integritee_solo_or_parachain, - get_validator_accessor_from_integritee_solo_or_parachain, - }, + utils::get_validator_accessor_from_integritee_solo_or_parachain, }; use base58::FromBase58; use codec::{Decode, Encode}; @@ -16,10 +12,6 @@ use core::result::Result; use ita_sgx_runtime::{Runtime, System, VERSION}; use ita_stf::{aes_encrypt_default, AesOutput, Getter, TrustedCallSigned}; use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, ExtrinsicSender}; -use itp_component_container::ComponentGetter; -use itp_node_api::metadata::{ - pallet_omni_account::OmniAccountCallIndexes, provider::AccessNodeMetadata, -}; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_primitives_cache::{GetPrimitives, GLOBAL_PRIMITIVES_CACHE}; use itp_rpc::RpcReturnValue; @@ -32,15 +24,14 @@ use itp_sgx_externalities::SgxExternalitiesTrait; use itp_stf_executor::getter_executor::ExecuteGetter; use itp_stf_state_handler::handle_state::HandleState; use itp_top_pool_author::traits::AuthorApi; -use itp_types::{DirectRequestStatus, Index, OpaqueCall, RsaRequest, ShardIdentifier, H256}; +use itp_types::{DirectRequestStatus, Index, RsaRequest, ShardIdentifier, H256}; use itp_utils::{FromHexPrefixed, ToHexPrefixed}; use its_rpc_handler::direct_top_pool_api::add_top_pool_direct_rpc_methods; use jsonrpc_core::{serde_json::json, IoHandler, Params, Value}; use lc_data_providers::DataProviderConfig; use lc_identity_verification::web2::{email, twitter}; -use lc_parachain_extrinsic_task_sender::{ParachainExtrinsicSender, SendParachainExtrinsic}; use litentry_macros::if_development; -use litentry_primitives::{aes_decrypt, AesRequest, DecryptableRequest, Identity, MemberAccount}; +use litentry_primitives::{aes_decrypt, AesRequest, DecryptableRequest, Identity}; use log::*; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::Pair; @@ -516,105 +507,6 @@ pub fn add_common_api Ok(json!(compute_hex_encoded_return_error("Could not parse params"))), } }); - - let local_state = state.clone(); - - io_handler.add_sync_method("omni_UploadIDGraph", move |params: Params| { - debug!("worker_api_direct rpc was called: omni_UploadIDGraph"); - let local_state = match local_state.clone() { - Some(s) => s, - None => - return Ok(json!(compute_hex_encoded_return_error( - "omni_UploadIDGraph is not avaiable" - ))), - }; - - match params.parse::<(String,)>() { - Ok((shard_base58,)) => { - let shard = match decode_shard_from_base58(shard_base58.as_str()) { - Ok(s) => s, - Err(msg) => { - let error_msg: String = - format!("Could not retrieve author_getNextNonce calls due to: {}", msg); - return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - }; - - let aes_key = - match GLOBAL_ACCOUNT_STORE_KEY_REPOSITORY_COMPONENT.get().and_then(|r| { - r.retrieve_key() - .map_err(|_| itp_component_container::error::Error::Other("".into())) - }) { - Ok(k) => k, - Err(e) => { - let error_msg = - format!("Cannot get AccountStore key repository: {:?}", e); - return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - }; - - let node_metadata_repo = - match get_node_metadata_repository_from_integritee_solo_or_parachain() { - Ok(r) => r, - Err(e) => - return Ok(json!(compute_hex_encoded_return_error( - format!("{:?}", e).as_str() - ))), - }; - - let call_index = match node_metadata_repo - .get_from_metadata(|m| m.update_account_store_by_one_call_indexes()) - { - Ok(r) => match r { - Ok(r) => r, - Err(e) => - return Ok(json!(compute_hex_encoded_return_error( - format!("{:?}", e).as_str() - ))), - }, - Err(e) => - return Ok(json!(compute_hex_encoded_return_error( - format!("{:?}", e).as_str() - ))), - }; - - let identities: Vec<(Identity, Identity)> = match local_state.load_cloned(&shard) { - Ok((mut state, _)) => state.execute_with(|| { - pallet_identity_management_tee::IDGraphs::::iter_keys().collect() - }), - Err(e) => - return Ok(json!(compute_hex_encoded_return_error( - format!("{:?}", e).as_str() - ))), - }; - - let sender = ParachainExtrinsicSender::new(); - info!("uploading {} identity pairs", identities.len()); - - for (prime_id, sub_id) in identities { - let member_account: MemberAccount = if prime_id == sub_id { - sub_id.into() - } else { - let enc_id: Vec = sub_id.encode(); - MemberAccount::Private( - aes_encrypt_default(&aes_key, &enc_id).encode(), - sub_id.hash(), - ) - }; - - let call = OpaqueCall::from_tuple(&(call_index, prime_id, member_account)); - - if let Err(e) = sender.send(call) { - return Ok(json!(compute_hex_encoded_return_error(e.as_str()))) - } - } - - let json_value = RpcReturnValue::new(vec![], false, DirectRequestStatus::Ok); - Ok(json!(json_value.to_hex())) - }, - Err(_) => Ok(json!(compute_hex_encoded_return_error("Could not parse params"))), - } - }); } #[deprecated(note = "`state_executeAesGetter` should be preferred")] From 39eab06b88fd554c41bc71606f76e4b62d016a51 Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Thu, 17 Oct 2024 10:17:25 +0000 Subject: [PATCH 11/13] fix clippy --- .../identity/enclave-runtime/src/initialization/mod.rs | 9 +++++---- .../identity/enclave-runtime/src/rpc/common_api.rs | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tee-worker/identity/enclave-runtime/src/initialization/mod.rs b/tee-worker/identity/enclave-runtime/src/initialization/mod.rs index 252e8b9b28..263ae6b0b3 100644 --- a/tee-worker/identity/enclave-runtime/src/initialization/mod.rs +++ b/tee-worker/identity/enclave-runtime/src/initialization/mod.rs @@ -127,7 +127,7 @@ pub(crate) fn init_enclave( let account_store_key_repository = Arc::new(create_aes256_repository(base_dir.clone(), "account_store", None)?); - GLOBAL_ACCOUNT_STORE_KEY_REPOSITORY_COMPONENT.initialize(account_store_key_repository.clone()); + GLOBAL_ACCOUNT_STORE_KEY_REPOSITORY_COMPONENT.initialize(account_store_key_repository); let integritee_light_client_seal = Arc::new(EnclaveLightClientSeal::new( base_dir.join(LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH), @@ -544,7 +544,8 @@ pub(crate) fn upload_id_graph() -> EnclaveResult<()> { let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; let shard = match state_handler.list_shards()? { - shards if shards.len() == 1 => shards[0], + shards if shards.len() == 1 => + *shards.get(0).ok_or_else(|| Error::Other("Shard len unexpected".into()))?, _ => return Err(Error::Other("Cannot get shard".into())), }; @@ -570,7 +571,7 @@ pub(crate) fn upload_id_graph() -> EnclaveResult<()> { calls.push(call); if calls.len() >= BATCH_SIZE { - let _ = extrinsic_factory + extrinsic_factory .create_batch_extrinsic(calls.drain(..).collect(), None) .map_err(|_| Error::Other("failed to create extrinsic".into())) .and_then(|ext| { @@ -582,7 +583,7 @@ pub(crate) fn upload_id_graph() -> EnclaveResult<()> { } if !calls.is_empty() { - let _ = extrinsic_factory + extrinsic_factory .create_batch_extrinsic(calls.drain(..).collect(), None) .map_err(|_| Error::Other("failed to create extrinsic".into())) .and_then(|ext| { diff --git a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs index 49e1289f42..9eb584c295 100644 --- a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs +++ b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs @@ -348,7 +348,7 @@ pub fn add_common_api Date: Thu, 17 Oct 2024 13:20:47 +0000 Subject: [PATCH 12/13] fix clippy --- .../identity/enclave-runtime/src/rpc/common_api.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs index 9eb584c295..48c85a11dc 100644 --- a/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs +++ b/tee-worker/identity/enclave-runtime/src/rpc/common_api.rs @@ -30,9 +30,9 @@ use its_rpc_handler::direct_top_pool_api::add_top_pool_direct_rpc_methods; use jsonrpc_core::{serde_json::json, IoHandler, Params, Value}; use lc_data_providers::DataProviderConfig; use lc_identity_verification::web2::{email, twitter}; -use litentry_macros::if_development; +use litentry_macros::{if_development, if_development_or}; use litentry_primitives::{aes_decrypt, AesRequest, DecryptableRequest, Identity}; -use log::*; +use log::debug; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::Pair; use sp_runtime::OpaqueExtrinsic; @@ -113,7 +113,7 @@ pub fn add_common_api s, None => return Ok(json!(compute_hex_encoded_return_error( From cc6d450e58fb7512fa97e9a84fb7717411cbeb82 Mon Sep 17 00:00:00 2001 From: Kailai Wang Date: Fri, 18 Oct 2024 13:26:06 +0000 Subject: [PATCH 13/13] fix test --- common/primitives/core/src/omni_account.rs | 3 +-- parachain/pallets/omni-account/src/lib.rs | 7 ++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/common/primitives/core/src/omni_account.rs b/common/primitives/core/src/omni_account.rs index c30a6cf715..fb2adc411f 100644 --- a/common/primitives/core/src/omni_account.rs +++ b/common/primitives/core/src/omni_account.rs @@ -17,8 +17,7 @@ use crate::{AccountId, Hash, Identity, Vec}; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_io::hashing::blake2_256; -use sp_runtime::{BoundedVec, RuntimeDebug}; +use sp_runtime::RuntimeDebug; #[derive(Encode, Decode, TypeInfo, Clone, PartialEq, Eq, RuntimeDebug)] pub enum MemberAccount { diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 89feb4fdcb..4346b61b1c 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -340,12 +340,9 @@ pub mod pallet { .map_err(|_| Error::::AccountStoreLenLimitReached)?; MemberAccountHash::::insert(hash, omni_account.clone()); - AccountStore::::insert(omni_account.clone(), member_accounts); + AccountStore::::insert(omni_account.clone(), member_accounts.clone()); - Self::deposit_event(Event::AccountStoreCreated { - who: omni_account, - account_store_hash: member_accounts.hash(), - }); + Self::deposit_event(Event::AccountStoreCreated { who: omni_account }); Ok(member_accounts) }