From ecdf920c12722a72126a6dec1ba43a97817aa3ff Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Wed, 11 Oct 2023 09:11:10 +0200 Subject: [PATCH 01/26] add design document with some mermaid diagrams --- DESIGN.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 DESIGN.md diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000000..c2529e5473 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,72 @@ +# sidechain startup internal view +```mermaid +sequenceDiagram + participant integritee_network + participant service + participant slotworker + participant parentsync + participant enclave + participant enclave_rpc + participant provisioningserver + participant isinitializedserver + participant metrics + service ->> enclave: EnclaveBase.get_mrenclave + service ->> provisioningserver: spawn (`--mu-ra-port` | 3443) + activate provisioningserver + service ->> enclave: get_ecc_signing_pubkey + service ->> isinitializedserver: spawn (`--untrusted-http-port | 4545) + activate isinitializedserver + service ->> metrics: spawn (`--metrics-port`| 8787) + activate metrics + service ->> enclave_rpc: spawn (`--trusted-worker-port`| 2000) + activate enclave_rpc + + service ->> enclave: generate_dcap_ra_extrinsic + service ->> integritee_network: send register_sgx_enclave extrinsic + service ->> integritee_network: get ShardStatus + service ->> isinitializedserver: registered_on_parentchain +# schedule teeracle re-registration and updates + loop while blocks to sync + service ->> integritee_network: get_block + service ->> enclave: sync_parentchain(blocks, events, proofs) + end + service ->> enclave: init_enclave_sidechain_components + service ->> slotworker: spawn + loop forever + slotworker ->> enclave: execute_trusted_calls + activate enclave + enclave ->> enclave: propose_sidechain_block + enclave ->> integritee_network: send_extrinsics + deactivate enclave + end + service ->> parentsync: spawn + loop forever + parentsync ->> integritee_network: subscribe new headers + parentsync ->> enclave: sync_parentchain + end + service ->> service: poll worker_for_shard + service ->> isinitializedserver: worker_for_shard_registered + + deactivate enclave_rpc + deactivate metrics + deactivate isinitializedserver + deactivate provisioningserver +``` + +# sidechain lifetime external view + +```mermaid +sequenceDiagram + participant integritee_network + participant validateer_1 + participant validateer_2 + actor alice + + validateer_1 ->> integritee_network: register_sgx_enclave() + + validateer_1 ->> integritee_network: register_sgx_enclave() + + validateer_2 ->> validateer_1: sidechain_fetchBlocksFromPeer() + + validateer_1 ->> validateer_2: sidechain_importBlock() +``` From 347e187c29b59c2089ce280b8283d263ee2f5e6f Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Wed, 11 Oct 2023 09:12:15 +0200 Subject: [PATCH 02/26] support enclave signing with changing keypairs at runtime --- core-primitives/extrinsics-factory/src/lib.rs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/core-primitives/extrinsics-factory/src/lib.rs b/core-primitives/extrinsics-factory/src/lib.rs index 2b226510c8..0744d1b657 100644 --- a/core-primitives/extrinsics-factory/src/lib.rs +++ b/core-primitives/extrinsics-factory/src/lib.rs @@ -88,6 +88,15 @@ where ) -> Self { ExtrinsicsFactory { genesis_hash, signer, nonce_cache, node_metadata_repository } } + + pub fn with_signer(&self, signer: Signer, nonce_cache: Arc) -> Self { + ExtrinsicsFactory { + genesis_hash: self.genesis_hash, + signer, + nonce_cache, + node_metadata_repository: self.node_metadata_repository.clone(), + } + } } impl CreateExtrinsics @@ -170,6 +179,33 @@ pub mod tests { assert_eq!(nonce_cache.get_nonce().unwrap(), Nonce(opaque_calls.len() as NonceValue)); } + #[test] + pub fn with_signer_works() { + let nonce_cache1 = Arc::new(NonceCache::default()); + *nonce_cache1.load_for_mutation().unwrap() = Nonce(42); + + let node_metadata_repo = Arc::new(NodeMetadataRepository::new(NodeMetadata::default())); + let extrinsics_factory = ExtrinsicsFactory::new( + test_genesis_hash(), + StaticExtrinsicSigner::<_, PairSignature>::new(test_account()), + nonce_cache1.clone(), + node_metadata_repo, + ); + + let nonce_cache2 = Arc::new(NonceCache::default()); + let extrinsics_factory = extrinsics_factory.with_signer( + StaticExtrinsicSigner::<_, PairSignature>::new(test_account2()), + nonce_cache2.clone(), + ); + + let opaque_calls = [OpaqueCall(vec![3u8; 42]), OpaqueCall(vec![12u8, 78])]; + let xts = extrinsics_factory.create_extrinsics(&opaque_calls, None).unwrap(); + + assert_eq!(opaque_calls.len(), xts.len()); + assert_eq!(nonce_cache2.get_nonce().unwrap(), Nonce(opaque_calls.len() as NonceValue)); + assert_eq!(nonce_cache1.get_nonce().unwrap(), Nonce(42)); + } + // #[test] // pub fn xts_have_increasing_nonce() { // let nonce_cache = Arc::new(NonceCache::default()); @@ -194,6 +230,10 @@ pub mod tests { ed25519::Pair::from_seed(b"42315678901234567890123456789012") } + fn test_account2() -> ed25519::Pair { + ed25519::Pair::from_seed(b"12315678901234567890123456789012") + } + fn test_genesis_hash() -> H256 { H256::from_slice(&[56u8; 32]) } From 81e94ddb44ef753862b14d93547942165b6b41dc Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Wed, 11 Oct 2023 12:51:56 +0200 Subject: [PATCH 03/26] tame nervous polling of not yet finalized block --- service/src/parentchain_handler.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/service/src/parentchain_handler.rs b/service/src/parentchain_handler.rs index 8b11e92b87..9ffae8c5b6 100644 --- a/service/src/parentchain_handler.rs +++ b/service/src/parentchain_handler.rs @@ -30,7 +30,7 @@ use log::*; use my_node_runtime::Header; use sp_consensus_grandpa::VersionedAuthorityList; use sp_runtime::traits::Header as HeaderTrait; -use std::{cmp::min, sync::Arc}; +use std::{cmp::min, sync::Arc, thread, time::Duration}; use substrate_api_client::ac_primitives::{Block, Header as HeaderT}; const BLOCK_SYNC_BATCH_SIZE: u32 = 1000; @@ -227,6 +227,8 @@ where while last_synced_header.number() < until_header.number() { last_synced_header = self.sync_parentchain(last_synced_header)?; trace!("[{:?}] synced block number: {}", id, last_synced_header.number); + // fast polling is useless because we only loop here if the target block hasn't been finalized yet + thread::sleep(Duration::from_millis(1000)); } self.trigger_parentchain_block_import()?; From 6ddd0434de15fb05e3c2c0ef09e6673d887bc6d2 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Wed, 11 Oct 2023 14:08:27 +0200 Subject: [PATCH 04/26] shard vault account creation works --- core-primitives/enclave-api/ffi/src/lib.rs | 7 ++ .../enclave-api/src/enclave_base.rs | 15 ++++ enclave-runtime/Enclave.edl | 4 + enclave-runtime/src/attestation.rs | 6 +- enclave-runtime/src/initialization/mod.rs | 75 +++++++++++++++++-- enclave-runtime/src/lib.rs | 16 ++++ enclave-runtime/src/teeracle/mod.rs | 6 +- enclave-runtime/src/top_pool_execution.rs | 6 +- enclave-runtime/src/utils.rs | 30 +++++++- service/src/main.rs | 23 ++++++ service/src/tests/mocks/enclave_api_mock.rs | 4 + 11 files changed, 175 insertions(+), 17 deletions(-) diff --git a/core-primitives/enclave-api/ffi/src/lib.rs b/core-primitives/enclave-api/ffi/src/lib.rs index cbdfcd09a0..1a39c488fa 100644 --- a/core-primitives/enclave-api/ffi/src/lib.rs +++ b/core-primitives/enclave-api/ffi/src/lib.rs @@ -57,6 +57,13 @@ extern "C" { shard_size: u32, ) -> sgx_status_t; + pub fn init_proxied_shard_vault( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + shard: *const u8, + shard_size: u32, + ) -> sgx_status_t; + pub fn trigger_parentchain_block_import( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, diff --git a/core-primitives/enclave-api/src/enclave_base.rs b/core-primitives/enclave-api/src/enclave_base.rs index def5d3ee47..454a69753c 100644 --- a/core-primitives/enclave-api/src/enclave_base.rs +++ b/core-primitives/enclave-api/src/enclave_base.rs @@ -56,6 +56,9 @@ pub trait EnclaveBase: Send + Sync + 'static { /// Initialize a new shard. fn init_shard(&self, shard: Vec) -> EnclaveResult<()>; + /// Initialize a new shard. + fn init_proxied_shard_vault(&self, shard: Vec) -> EnclaveResult<()>; + /// Trigger the import of parentchain block explicitly. Used when initializing a light-client /// with a triggered import dispatcher. fn trigger_parentchain_block_import(&self, parentchain_id: &ParentchainId) @@ -164,6 +167,18 @@ impl EnclaveBase for Enclave { Ok(()) } + fn init_proxied_shard_vault(&self, shard: Vec) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { + ffi::init_proxied_shard_vault(self.eid, &mut retval, shard.as_ptr(), shard.len() as u32) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } fn trigger_parentchain_block_import( &self, parentchain_id: &ParentchainId, diff --git a/enclave-runtime/Enclave.edl b/enclave-runtime/Enclave.edl index c8cf058ec1..fcd63761a6 100644 --- a/enclave-runtime/Enclave.edl +++ b/enclave-runtime/Enclave.edl @@ -58,6 +58,10 @@ enclave { [in, size=shard_size] uint8_t* shard, uint32_t shard_size ); + public sgx_status_t init_proxied_shard_vault( + [in, size=shard_size] uint8_t* shard, uint32_t shard_size + ); + public sgx_status_t trigger_parentchain_block_import( [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size ); diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index ae609f279b..857578c431 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -30,7 +30,7 @@ use crate::{ initialization::global_components::GLOBAL_ATTESTATION_HANDLER_COMPONENT, utils::{ - get_extrinsic_factory_from_solo_or_parachain, + get_extrinsic_factory_from_integritee_solo_or_parachain, get_node_metadata_repository_from_integritee_solo_or_parachain, }, Error as EnclaveError, Result as EnclaveResult, @@ -381,7 +381,7 @@ pub fn generate_ias_skip_ra_extrinsic_from_der_cert_internal( } fn create_extrinsics(call: OpaqueCall) -> EnclaveResult { - let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; let extrinsics = extrinsics_factory.create_extrinsics(&[call], None)?; Ok(extrinsics[0].clone()) @@ -459,7 +459,7 @@ pub fn generate_generic_register_collateral_extrinsic( where F: Fn(&NodeMetadata) -> Result<[u8; 2], MetadataError>, { - let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; let call_ids = node_metadata_repo diff --git a/enclave-runtime/src/initialization/mod.rs b/enclave-runtime/src/initialization/mod.rs index 0573c11c5c..8ad8799c4e 100644 --- a/enclave-runtime/src/initialization/mod.rs +++ b/enclave-runtime/src/initialization/mod.rs @@ -41,7 +41,7 @@ use crate::{ ocall::OcallApi, rpc::{rpc_response_channel::RpcResponseChannel, worker_api_direct::public_api_rpc_handler}, utils::{ - get_extrinsic_factory_from_solo_or_parachain, + get_extrinsic_factory_from_integritee_solo_or_parachain, get_node_metadata_repository_from_integritee_solo_or_parachain, get_triggered_dispatcher_from_solo_or_parachain, get_validator_accessor_from_solo_or_parachain, @@ -49,7 +49,7 @@ use crate::{ Hash, }; use base58::ToBase58; -use codec::Encode; +use codec::{Compact, Encode}; use itc_direct_rpc_server::{ create_determine_watch, rpc_connection_registry::ConnectionRegistry, rpc_ws_handler::RpcWsHandler, @@ -60,6 +60,13 @@ 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::{ + api_client::{PairSignature, StaticExtrinsicSigner}, + metadata::provider::{AccessNodeMetadata, Error as MetadataProviderError}, +}; +use itp_nonce_cache::NonceCache; +use itp_ocall_api::EnclaveOnChainOCallApi; use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE; use itp_settings::files::{ INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE, @@ -75,12 +82,18 @@ use itp_stf_state_handler::{ }; use itp_top_pool::pool::Options as PoolOptions; use itp_top_pool_author::author::AuthorTopFilter; -use itp_types::{parentchain::ParentchainId, ShardIdentifier}; +use itp_types::{ + parentchain::{AccountId, Address, Balance, ParentchainId}, + OpaqueCall, ShardIdentifier, +}; use its_sidechain::block_composer::BlockComposer; use log::*; -use sp_core::crypto::Pair; +use sp_core::{ + blake2_256, + crypto::{DeriveJunction, Pair}, + ed25519, +}; use std::{collections::HashMap, path::PathBuf, string::String, sync::Arc}; - pub(crate) fn init_enclave( mu_ra_url: String, untrusted_worker_url: String, @@ -226,7 +239,7 @@ pub(crate) fn init_enclave_sidechain_components() -> EnclaveResult<()> { let sidechain_block_import_queue = GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT.get()?; let metadata_repository = get_node_metadata_repository_from_integritee_solo_or_parachain()?; - let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; let validator_accessor = get_validator_accessor_from_solo_or_parachain()?; let sidechain_block_import_confirmation_handler = @@ -289,6 +302,56 @@ pub(crate) fn init_shard(shard: ShardIdentifier) -> EnclaveResult<()> { Ok(()) } +pub(crate) fn init_proxied_shard_vault(shard: ShardIdentifier) -> EnclaveResult<()> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + if !state_handler.shard_exists(&shard).unwrap() { + return Err(Error::Other("shard not initialized".into())) + }; + + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let enclave_signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; + let enclave_extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + let vault = enclave_signer + .derive(vec![DeriveJunction::hard(shard.encode())].into_iter(), None) + .map_err(|e| Error::Other("failed to derive shard vault keypair".into()))? + .0; + + info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0.clone())); + + // todo! + // parentchain-query: if shard vault not yet existing or self not proxy: + + // xt: send funds from enclave account to new vault account (panic if not enough funds) + + info!("send existential funds from enclave account to vault account"); + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.call_indexes("Balances", "transfer_keep_alive"))? + .map_err(MetadataProviderError::MetadataError)?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + Address::from(AccountId::from(vault.public().0)), + Compact(Balance::from(20_000_000_000_000u128)), + )); + + info!("vault funding call: 0x{}", hex::encode(call.0.clone())); + let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; + + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee); + + let nonce_cache = Arc::new(NonceCache::default()); + let vault_extrinsics_factory = enclave_extrinsics_factory + .with_signer(StaticExtrinsicSigner::<_, PairSignature>::new(vault), nonce_cache); + + // xt: delegate proxy authority to its own enclave accountid proxy.add_proxy() (panic if fails) + // caveat: must send from vault account. how to sign extrinsics with other keypair? + // sth like: extrinsics_factory.with_signer(keypair).create_extrinsics( + // write vault accountid to STF State (SgxExternalitiesType) with key ShardVaultAccountId to make it available also beyond service restart for non-primary SCV later + // return and log vault accountId + Ok(()) +} + /// Initialize the TOP pool author component. pub fn create_top_pool_author( connection_registry: Arc, diff --git a/enclave-runtime/src/lib.rs b/enclave-runtime/src/lib.rs index 3379bcfe4b..69c2a00192 100644 --- a/enclave-runtime/src/lib.rs +++ b/enclave-runtime/src/lib.rs @@ -428,6 +428,22 @@ pub unsafe extern "C" fn init_shard(shard: *const u8, shard_size: u32) -> sgx_st sgx_status_t::SGX_SUCCESS } +#[no_mangle] +pub unsafe extern "C" fn init_proxied_shard_vault( + shard: *const u8, + shard_size: u32, +) -> sgx_status_t { + let shard_identifier = + ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); + + if let Err(e) = initialization::init_proxied_shard_vault(shard_identifier) { + error!("Failed to initialize proxied shard vault ({:?}): {:?}", shard_identifier, 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/enclave-runtime/src/teeracle/mod.rs b/enclave-runtime/src/teeracle/mod.rs index 460357fc94..75f378c9a0 100644 --- a/enclave-runtime/src/teeracle/mod.rs +++ b/enclave-runtime/src/teeracle/mod.rs @@ -19,7 +19,7 @@ use crate::{ error::{Error, Result}, initialization::global_components::GLOBAL_OCALL_API_COMPONENT, utils::{ - get_extrinsic_factory_from_solo_or_parachain, + get_extrinsic_factory_from_integritee_solo_or_parachain, get_node_metadata_repository_from_integritee_solo_or_parachain, }, }; @@ -46,7 +46,7 @@ use sp_runtime::OpaqueExtrinsic; use std::{string::String, vec::Vec}; fn update_weather_data_internal(weather_info: WeatherInfo) -> Result> { - let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; let mut extrinsic_calls: Vec = Vec::new(); @@ -198,7 +198,7 @@ fn update_market_data_internal( crypto_currency: String, fiat_currency: String, ) -> Result> { - let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; let mut extrinsic_calls: Vec = Vec::new(); diff --git a/enclave-runtime/src/top_pool_execution.rs b/enclave-runtime/src/top_pool_execution.rs index fbcad96947..7fc1dd1541 100644 --- a/enclave-runtime/src/top_pool_execution.rs +++ b/enclave-runtime/src/top_pool_execution.rs @@ -24,8 +24,8 @@ use crate::{ }, sync::{EnclaveLock, EnclaveStateRWLock}, utils::{ - get_extrinsic_factory_from_solo_or_parachain, get_stf_executor_from_solo_or_parachain, - get_triggered_dispatcher_from_solo_or_parachain, + get_extrinsic_factory_from_integritee_solo_or_parachain, + get_stf_executor_from_solo_or_parachain, get_triggered_dispatcher_from_solo_or_parachain, get_validator_accessor_from_solo_or_parachain, }, }; @@ -123,7 +123,7 @@ fn execute_top_pool_trusted_calls_internal() -> Result<()> { let block_composer = GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT.get()?; - let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; diff --git a/enclave-runtime/src/utils.rs b/enclave-runtime/src/utils.rs index 7635385d7c..7249e53dab 100644 --- a/enclave-runtime/src/utils.rs +++ b/enclave-runtime/src/utils.rs @@ -147,8 +147,8 @@ pub(crate) fn get_node_metadata_repository_from_target_b_solo_or_parachain( Ok(metadata_repository) } -pub(crate) fn get_extrinsic_factory_from_solo_or_parachain() -> Result> -{ +pub(crate) fn get_extrinsic_factory_from_integritee_solo_or_parachain( +) -> Result> { let extrinsics_factory = if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { solochain_handler.extrinsics_factory.clone() @@ -160,6 +160,32 @@ pub(crate) fn get_extrinsic_factory_from_solo_or_parachain() -> Result Result> { + let extrinsics_factory = + if let Ok(solochain_handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.extrinsics_factory.clone() + } else if let Ok(parachain_handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.extrinsics_factory.clone() + } else { + return Err(Error::NoTargetAParentchainAssigned) + }; + Ok(extrinsics_factory) +} + +pub(crate) fn get_extrinsic_factory_from_target_b_solo_or_parachain( +) -> Result> { + let extrinsics_factory = + if let Ok(solochain_handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.extrinsics_factory.clone() + } else if let Ok(parachain_handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.extrinsics_factory.clone() + } else { + return Err(Error::NoTargetBParentchainAssigned) + }; + Ok(extrinsics_factory) +} + pub(crate) fn get_stf_executor_from_solo_or_parachain() -> Result> { let stf_executor = if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { diff --git a/service/src/main.rs b/service/src/main.rs index 3fd1f3401c..49d429e98d 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -593,6 +593,9 @@ fn start_worker( println!("[!] Parentchain block syncing has terminated"); }) .unwrap(); + + println!("initializing proxied shard vault account now"); + enclave.init_proxied_shard_vault(shard.encode()); } // ------------------------------------------------------------------------ @@ -605,6 +608,7 @@ fn start_worker( &enclave, &tee_accountid, url, + shard, ParentchainId::TargetA, is_development_mode, ) @@ -615,6 +619,7 @@ fn start_worker( &enclave, &tee_accountid, url, + shard, ParentchainId::TargetB, is_development_mode, ) @@ -636,6 +641,7 @@ fn init_target_parentchain( enclave: &Arc, tee_account_id: &AccountId32, url: String, + shard: &ShardIdentifier, parentchain_id: ParentchainId, is_development_mode: bool, ) where @@ -665,6 +671,17 @@ fn init_target_parentchain( let last_synched_header = parentchain_handler.sync_parentchain(last_synched_header).unwrap(); + //setup_proxied_shard_vault + //println!("initializing proxied shard vault account now"); + // todo: generic for targetA/B + //enclave.init_proxied_shard_vault(shard.encode()); + + // if we are primary validateer and if doesn't exist, create a pure_proxy for shard vault + // todo + + // check if exists + //tee_account_id + // start parentchain syncing loop (subscribe to header updates) thread::Builder::new() .name(format!("{:?}_parentchain_sync_loop", parentchain_id)) @@ -735,6 +752,12 @@ where panic!("[{:?}] Could not set the node metadata in the enclave", parentchain_id) }); + // todo!: ensure shard vault proxy exists + // should only be registered by primary worker for shard + // check if metadata contains proxy pallet and issue warning otherwise + // check if shard vault exists (must derive accountid from primary worker and index + // let enclave compose proxy.create_pure(proxyType: Any, delay:0, index:0) + (parentchain_handler, last_synced_header) } diff --git a/service/src/tests/mocks/enclave_api_mock.rs b/service/src/tests/mocks/enclave_api_mock.rs index 7c93116273..2bcee8a60e 100644 --- a/service/src/tests/mocks/enclave_api_mock.rs +++ b/service/src/tests/mocks/enclave_api_mock.rs @@ -60,6 +60,10 @@ impl EnclaveBase for EnclaveMock { unimplemented!() } + fn init_proxied_shard_vault(&self, _shard: Vec) -> EnclaveResult<()> { + unimplemented!() + } + fn trigger_parentchain_block_import(&self, _: &ParentchainId) -> EnclaveResult<()> { unimplemented!() } From 156aac3cf78da1bccfd36a36361e830ff8e99ab4 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Wed, 11 Oct 2023 17:27:35 +0200 Subject: [PATCH 05/26] prepare vault account getter. not working yet --- app-libs/stf/src/trusted_call.rs | 1 + core-primitives/enclave-api/ffi/src/lib.rs | 7 +++ .../enclave-api/src/enclave_base.rs | 21 +++++++++ core-primitives/stf-interface/src/lib.rs | 2 + core-primitives/types/src/parentchain.rs | 9 ++++ enclave-runtime/Cargo.lock | 46 +++++++++---------- enclave-runtime/Enclave.edl | 4 ++ enclave-runtime/src/initialization/mod.rs | 24 +++++++++- enclave-runtime/src/lib.rs | 32 +++++++++++++ 9 files changed, 122 insertions(+), 24 deletions(-) diff --git a/app-libs/stf/src/trusted_call.rs b/app-libs/stf/src/trusted_call.rs index c81d21eadc..ccaa813520 100644 --- a/app-libs/stf/src/trusted_call.rs +++ b/app-libs/stf/src/trusted_call.rs @@ -242,6 +242,7 @@ where shard ); unshield_funds(account_incognito, value)?; + calls.push(OpaqueCall::from_tuple(&( node_metadata_repo.get_from_metadata(|m| m.unshield_funds_call_indexes())??, shard, diff --git a/core-primitives/enclave-api/ffi/src/lib.rs b/core-primitives/enclave-api/ffi/src/lib.rs index 1a39c488fa..79fe5508a2 100644 --- a/core-primitives/enclave-api/ffi/src/lib.rs +++ b/core-primitives/enclave-api/ffi/src/lib.rs @@ -117,6 +117,13 @@ extern "C" { pubkey_size: u32, ) -> sgx_status_t; + pub fn get_ecc_vault_pubkey( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + pubkey: *mut u8, + pubkey_size: u32, + ) -> sgx_status_t; + pub fn get_mrenclave( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, diff --git a/core-primitives/enclave-api/src/enclave_base.rs b/core-primitives/enclave-api/src/enclave_base.rs index 454a69753c..7b83a75b9a 100644 --- a/core-primitives/enclave-api/src/enclave_base.rs +++ b/core-primitives/enclave-api/src/enclave_base.rs @@ -76,6 +76,8 @@ pub trait EnclaveBase: Send + Sync + 'static { fn get_ecc_signing_pubkey(&self) -> EnclaveResult; + fn get_ecc_vault_pubkey(&self, shard: Vec) -> EnclaveResult; + fn get_fingerprint(&self) -> EnclaveResult; } @@ -291,6 +293,25 @@ impl EnclaveBase for Enclave { Ok(ed25519::Public::from_raw(pubkey)) } + fn get_ecc_vault_pubkey(&self, shard: Vec) -> EnclaveResult { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut pubkey = [0u8; SIGNING_KEY_SIZE]; + + let result = unsafe { + ffi::get_ecc_vault_pubkey( + self.eid, + &mut retval, + pubkey.as_mut_ptr(), + pubkey.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(ed25519::Public::from_raw(pubkey)) + } + fn get_fingerprint(&self) -> EnclaveResult { let mut retval = sgx_status_t::SGX_SUCCESS; let mut mr_enclave = [0u8; MR_ENCLAVE_SIZE]; diff --git a/core-primitives/stf-interface/src/lib.rs b/core-primitives/stf-interface/src/lib.rs index 66ae77495b..e88104351e 100644 --- a/core-primitives/stf-interface/src/lib.rs +++ b/core-primitives/stf-interface/src/lib.rs @@ -33,6 +33,8 @@ pub mod parentchain_pallet; pub mod sudo_pallet; pub mod system_pallet; +pub const SHARD_VAULT_KEY: &str = "ShardVaultPubKey"; + /// Interface to initialize a new state. pub trait InitState { /// Initialize a new state for a given enclave account. diff --git a/core-primitives/types/src/parentchain.rs b/core-primitives/types/src/parentchain.rs index 32610d0aa9..6439929129 100644 --- a/core-primitives/types/src/parentchain.rs +++ b/core-primitives/types/src/parentchain.rs @@ -33,6 +33,15 @@ pub type AccountId = sp_core::crypto::AccountId32; pub type AccountData = pallet_balances::AccountData; pub type AccountInfo = frame_system::AccountInfo; pub type Address = MultiAddress; +// todo! make generic +/// The type used to represent the kinds of proxying allowed. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +pub enum ProxyType { + Any, + NonTransfer, + Governance, + Staking, +} // Block Types pub type BlockNumber = u32; diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index cbdc7d892f..f38d112465 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -257,7 +257,7 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "binary-merkle-tree" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db 0.16.0", ] @@ -1083,7 +1083,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -1196,7 +1196,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-api", @@ -2960,7 +2960,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "pallet-aura" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -2976,7 +2976,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -2990,7 +2990,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -3026,7 +3026,7 @@ dependencies = [ [[package]] name = "pallet-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -3048,7 +3048,7 @@ dependencies = [ [[package]] name = "pallet-insecure-randomness-collective-flip" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -3078,7 +3078,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -3098,7 +3098,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -3112,7 +3112,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -3128,7 +3128,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -3143,7 +3143,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -4218,7 +4218,7 @@ dependencies = [ [[package]] name = "sp-block-builder" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-api", @@ -4230,7 +4230,7 @@ dependencies = [ [[package]] name = "sp-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -4246,7 +4246,7 @@ dependencies = [ [[package]] name = "sp-consensus-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "finality-grandpa", "log", @@ -4262,7 +4262,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -4394,7 +4394,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "sp-api", "sp-core", @@ -4454,7 +4454,7 @@ dependencies = [ [[package]] name = "sp-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -4495,7 +4495,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-inherents", @@ -4517,7 +4517,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "sp-api", "sp-runtime", @@ -4526,7 +4526,7 @@ dependencies = [ [[package]] name = "sp-trie" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#569aae5341ea0c1d10426fa1ec13a36c0b64393b" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db 0.16.0", "memory-db", @@ -4884,7 +4884,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 0.1.10", "digest 0.10.7", "static_assertions", ] diff --git a/enclave-runtime/Enclave.edl b/enclave-runtime/Enclave.edl index fcd63761a6..fee38e2274 100644 --- a/enclave-runtime/Enclave.edl +++ b/enclave-runtime/Enclave.edl @@ -91,6 +91,10 @@ enclave { public sgx_status_t get_ecc_signing_pubkey( [out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size); + public sgx_status_t get_ecc_vault_pubkey( + [in, size=shard_size] uint8_t* shard, uint32_t shard_size + [out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size); + public sgx_status_t get_mrenclave( [out, size=mrenclave_size] uint8_t* mrenclave, uint32_t mrenclave_size); diff --git a/enclave-runtime/src/initialization/mod.rs b/enclave-runtime/src/initialization/mod.rs index 8ad8799c4e..3490d251df 100644 --- a/enclave-runtime/src/initialization/mod.rs +++ b/enclave-runtime/src/initialization/mod.rs @@ -75,6 +75,8 @@ 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_interface::SHARD_VAULT_KEY; use itp_stf_state_handler::{ file_io::StateDir, handle_state::HandleState, query_shard_state::QueryShardState, state_snapshot_repository::VersionedStateAccess, @@ -83,7 +85,7 @@ use itp_stf_state_handler::{ use itp_top_pool::pool::Options as PoolOptions; use itp_top_pool_author::author::AuthorTopFilter; use itp_types::{ - parentchain::{AccountId, Address, Balance, ParentchainId}, + parentchain::{AccountId, Address, Balance, ParentchainId, ProxyType}, OpaqueCall, ShardIdentifier, }; use its_sidechain::block_composer::BlockComposer; @@ -319,6 +321,9 @@ pub(crate) fn init_proxied_shard_vault(shard: ShardIdentifier) -> EnclaveResult< info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0.clone())); + let (state_lock, mut state) = state_handler.load_for_mutation(&shard)?; + state.state.insert(SHARD_VAULT_KEY.into(), vault.public().0.to_vec()); + state_handler.write_after_mutation(state, state_lock, &shard)?; // todo! // parentchain-query: if shard vault not yet existing or self not proxy: @@ -344,6 +349,23 @@ pub(crate) fn init_proxied_shard_vault(shard: ShardIdentifier) -> EnclaveResult< let vault_extrinsics_factory = enclave_extrinsics_factory .with_signer(StaticExtrinsicSigner::<_, PairSignature>::new(vault), nonce_cache); + info!("register enclave signer as proxy for shard vault"); + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.call_indexes("Proxy", "add_proxy"))? + .map_err(MetadataProviderError::MetadataError)?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + Address::from(AccountId::from(enclave_signer.public().0)), + ProxyType::Any, + 0u32, // delay + )); + + info!("add proxy call: 0x{}", hex::encode(call.0.clone())); + let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; + + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee); + // xt: delegate proxy authority to its own enclave accountid proxy.add_proxy() (panic if fails) // caveat: must send from vault account. how to sign extrinsics with other keypair? // sth like: extrinsics_factory.with_signer(keypair).create_extrinsics( diff --git a/enclave-runtime/src/lib.rs b/enclave-runtime/src/lib.rs index 69c2a00192..6a90f57c3d 100644 --- a/enclave-runtime/src/lib.rs +++ b/enclave-runtime/src/lib.rs @@ -60,6 +60,8 @@ use itp_node_api::metadata::NodeMetadata; use itp_nonce_cache::{MutateNonce, Nonce}; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; use itp_sgx_crypto::key_repository::AccessPubkey; +use itp_stf_interface::SHARD_VAULT_KEY; +use itp_stf_state_handler::handle_state::HandleState; use itp_storage::{StorageProof, StorageProofChecker}; use itp_types::{ShardIdentifier, SignedBlock}; use itp_utils::write_slice_and_whitespace_pad; @@ -218,6 +220,36 @@ pub unsafe extern "C" fn get_ecc_signing_pubkey(pubkey: *mut u8, pubkey_size: u3 sgx_status_t::SGX_SUCCESS } +#[no_mangle] +pub unsafe extern "C" fn get_ecc_vault_pubkey( + shard: *const u8, + shard_size: u32, + pubkey: *mut u8, + pubkey_size: u32, +) -> sgx_status_t { + let shard = ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); + let state_handler = match GLOBAL_STATE_HANDLER_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + /*let vault_pubkey: Vec = state_handler + .execute_on_current(&shard, |state, _| state.state.get::>(&SHARD_VAULT_KEY.into())) + .unwrap() + .unwrap() + .to_vec(); + + let pubkey_slice = slice::from_raw_parts_mut(pubkey, pubkey_size as usize); + //debug!("Restored ECC pubkey: {:?}", signer_public); + + pubkey_slice.clone_from_slice(&vault_pubkey); + */ + sgx_status_t::SGX_ERROR_UNEXPECTED +} + #[no_mangle] pub unsafe extern "C" fn set_nonce( nonce: *const u32, From f1d3d7793ce7340b497dd1f5f298dd6aa315eb41 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 12 Oct 2023 07:47:37 +0200 Subject: [PATCH 06/26] fix build and add trusted_call dummy for unshielding --- app-libs/stf/src/trusted_call.rs | 25 +++++++++-- core-primitives/enclave-api/ffi/src/lib.rs | 2 + .../enclave-api/src/enclave_base.rs | 2 + core-primitives/node-api/metadata/src/lib.rs | 19 ++++++-- .../node-api/metadata/src/metadata_mocks.rs | 43 ++++++++++++++++++- .../node-api/metadata/src/pallet_balances.rs | 6 +++ .../node-api/metadata/src/pallet_proxy.rs | 37 ++++++++++++++++ enclave-runtime/Enclave.edl | 2 +- service/src/tests/mocks/enclave_api_mock.rs | 4 ++ 9 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 core-primitives/node-api/metadata/src/pallet_proxy.rs diff --git a/app-libs/stf/src/trusted_call.rs b/app-libs/stf/src/trusted_call.rs index ccaa813520..590c119854 100644 --- a/app-libs/stf/src/trusted_call.rs +++ b/app-libs/stf/src/trusted_call.rs @@ -22,15 +22,17 @@ use sp_core::{H160, H256, U256}; use std::vec::Vec; use crate::{helpers::ensure_enclave_signer_account, StfError, TrustedOperation}; -use codec::{Decode, Encode}; +use codec::{Compact, Decode, Encode}; use frame_support::{ensure, traits::UnfilteredDispatchable}; pub use ita_sgx_runtime::{Balance, Index}; use ita_sgx_runtime::{Runtime, System}; use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; -use itp_node_api_metadata::pallet_enclave_bridge::EnclaveBridgeCallIndexes; +use itp_node_api_metadata::{ + pallet_enclave_bridge::EnclaveBridgeCallIndexes, pallet_proxy::ProxyCallIndexes, +}; use itp_stf_interface::ExecuteCall; use itp_stf_primitives::types::{AccountId, KeyPair, ShardIdentifier, Signature}; -use itp_types::OpaqueCall; +use itp_types::{Address, OpaqueCall}; use itp_utils::stringify::account_id_to_string; use log::*; use sp_io::hashing::blake2_256; @@ -246,10 +248,25 @@ where calls.push(OpaqueCall::from_tuple(&( node_metadata_repo.get_from_metadata(|m| m.unshield_funds_call_indexes())??, shard, - beneficiary, + beneficiary.clone(), value, call_hash, ))); + // todo: the following is a placeholder dummy which will replace the above with #1257 + // todo: insert correct vault accountid here + let vault_address = Address::from(AccountId::from([0u8; 32])); + let vault_transfer_call = OpaqueCall::from_tuple(&( + //node_metadata_repo + // .get_from_metadata(|m| m.transfer_keep_alive_call_indexes())??, + [0u8, 0u8], + Address::from(beneficiary), + Compact(value), + )); + calls.push(OpaqueCall::from_tuple(&( + node_metadata_repo.get_from_metadata(|m| m.proxy_call_indexes())??, + vault_address, + vault_transfer_call, + ))); Ok(()) }, TrustedCall::balance_shield(enclave_account, who, value) => { diff --git a/core-primitives/enclave-api/ffi/src/lib.rs b/core-primitives/enclave-api/ffi/src/lib.rs index 79fe5508a2..12115521e1 100644 --- a/core-primitives/enclave-api/ffi/src/lib.rs +++ b/core-primitives/enclave-api/ffi/src/lib.rs @@ -120,6 +120,8 @@ extern "C" { pub fn get_ecc_vault_pubkey( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, + shard: *const u8, + shard_size: u32, pubkey: *mut u8, pubkey_size: u32, ) -> sgx_status_t; diff --git a/core-primitives/enclave-api/src/enclave_base.rs b/core-primitives/enclave-api/src/enclave_base.rs index 7b83a75b9a..6b317d8b9f 100644 --- a/core-primitives/enclave-api/src/enclave_base.rs +++ b/core-primitives/enclave-api/src/enclave_base.rs @@ -301,6 +301,8 @@ impl EnclaveBase for Enclave { ffi::get_ecc_vault_pubkey( self.eid, &mut retval, + shard.as_ptr(), + shard.len() as u32, pubkey.as_mut_ptr(), pubkey.len() as u32, ) diff --git a/core-primitives/node-api/metadata/src/lib.rs b/core-primitives/node-api/metadata/src/lib.rs index 55f66e35dc..648876eb40 100644 --- a/core-primitives/node-api/metadata/src/lib.rs +++ b/core-primitives/node-api/metadata/src/lib.rs @@ -20,7 +20,8 @@ #![cfg_attr(not(feature = "std"), no_std)] use crate::{ - error::Result, pallet_enclave_bridge::EnclaveBridgeCallIndexes, + error::Result, pallet_balances::BalancesCallIndexes, + pallet_enclave_bridge::EnclaveBridgeCallIndexes, pallet_proxy::ProxyCallIndexes, pallet_sidechain::SidechainCallIndexes, pallet_teerex::TeerexCallIndexes, }; use codec::{Decode, Encode}; @@ -32,6 +33,7 @@ pub use itp_api_client_types::{Metadata, MetadataError}; pub mod error; pub mod pallet_balances; pub mod pallet_enclave_bridge; +pub mod pallet_proxy; pub mod pallet_sidechain; pub mod pallet_teeracle; pub mod pallet_teerex; @@ -40,11 +42,20 @@ pub mod pallet_teerex; pub mod metadata_mocks; pub trait NodeMetadataTrait: - TeerexCallIndexes + EnclaveBridgeCallIndexes + SidechainCallIndexes + TeerexCallIndexes + + EnclaveBridgeCallIndexes + + SidechainCallIndexes + + ProxyCallIndexes + + BalancesCallIndexes { } -impl NodeMetadataTrait - for T +impl< + T: TeerexCallIndexes + + EnclaveBridgeCallIndexes + + SidechainCallIndexes + + ProxyCallIndexes + + BalancesCallIndexes, + > NodeMetadataTrait for T { } diff --git a/core-primitives/node-api/metadata/src/metadata_mocks.rs b/core-primitives/node-api/metadata/src/metadata_mocks.rs index 57cf0fe327..d9cecefc97 100644 --- a/core-primitives/node-api/metadata/src/metadata_mocks.rs +++ b/core-primitives/node-api/metadata/src/metadata_mocks.rs @@ -16,11 +16,12 @@ */ use crate::{ - error::Result, pallet_sidechain::SidechainCallIndexes, pallet_teerex::TeerexCallIndexes, + error::Result, pallet_balances::BalancesCallIndexes, + pallet_enclave_bridge::EnclaveBridgeCallIndexes, pallet_proxy::ProxyCallIndexes, + pallet_sidechain::SidechainCallIndexes, pallet_teerex::TeerexCallIndexes, }; use codec::{Decode, Encode}; -use crate::pallet_enclave_bridge::EnclaveBridgeCallIndexes; use itp_api_client_types::Metadata; impl TryFrom for Metadata { @@ -48,6 +49,13 @@ pub struct NodeMetadataMock { update_shard_config: u8, sidechain_module: u8, imported_sidechain_block: u8, + proxy_module: u8, + add_proxy: u8, + proxy: u8, + balances_module: u8, + transfer: u8, + transfer_keep_alive: u8, + transfer_allow_death: u8, runtime_spec_version: u32, runtime_transaction_version: u32, } @@ -70,6 +78,13 @@ impl NodeMetadataMock { update_shard_config: 5u8, sidechain_module: 53u8, imported_sidechain_block: 0u8, + proxy_module: 7u8, + add_proxy: 1u8, + proxy: 0u8, + balances_module: 10u8, + transfer: 7u8, + transfer_keep_alive: 3u8, + transfer_allow_death: 0u8, runtime_spec_version: 25, runtime_transaction_version: 4, } @@ -129,3 +144,27 @@ impl SidechainCallIndexes for NodeMetadataMock { Ok([self.sidechain_module, self.imported_sidechain_block]) } } + +impl ProxyCallIndexes for NodeMetadataMock { + fn add_proxy_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.proxy_module, self.add_proxy]) + } + + fn proxy_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.proxy_module, self.proxy]) + } +} + +impl BalancesCallIndexes for NodeMetadataMock { + fn transfer_call_index(&self) -> Result<[u8; 2]> { + Ok([self.balances_module, self.transfer]) + } + + fn transfer_keep_alive_call_index(&self) -> Result<[u8; 2]> { + Ok([self.balances_module, self.transfer_keep_alive]) + } + + fn transfer_allow_death_call_index(&self) -> Result<[u8; 2]> { + Ok([self.balances_module, self.transfer_allow_death]) + } +} diff --git a/core-primitives/node-api/metadata/src/pallet_balances.rs b/core-primitives/node-api/metadata/src/pallet_balances.rs index 185f0efff3..73f3b2e889 100644 --- a/core-primitives/node-api/metadata/src/pallet_balances.rs +++ b/core-primitives/node-api/metadata/src/pallet_balances.rs @@ -23,6 +23,8 @@ const BALANCES: &str = "Balances"; pub trait BalancesCallIndexes { fn transfer_call_index(&self) -> Result<[u8; 2]>; + fn transfer_keep_alive_call_index(&self) -> Result<[u8; 2]>; + fn transfer_allow_death_call_index(&self) -> Result<[u8; 2]>; } @@ -31,6 +33,10 @@ impl BalancesCallIndexes for NodeMetadata { self.call_indexes(BALANCES, "transfer") } + fn transfer_keep_alive_call_index(&self) -> Result<[u8; 2]> { + self.call_indexes(BALANCES, "transfer_keep_alive") + } + fn transfer_allow_death_call_index(&self) -> Result<[u8; 2]> { self.call_indexes(BALANCES, "transfer_allow_death") } diff --git a/core-primitives/node-api/metadata/src/pallet_proxy.rs b/core-primitives/node-api/metadata/src/pallet_proxy.rs new file mode 100644 index 0000000000..a0106457b0 --- /dev/null +++ b/core-primitives/node-api/metadata/src/pallet_proxy.rs @@ -0,0 +1,37 @@ +/* + 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. + +*/ + +use crate::{error::Result, NodeMetadata}; + +/// Pallet name: +const PROXY: &str = "Proxy"; + +pub trait ProxyCallIndexes { + fn add_proxy_call_indexes(&self) -> Result<[u8; 2]>; + + fn proxy_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl ProxyCallIndexes for NodeMetadata { + fn add_proxy_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(PROXY, "add_proxy") + } + + fn proxy_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(PROXY, "proxy") + } +} diff --git a/enclave-runtime/Enclave.edl b/enclave-runtime/Enclave.edl index fee38e2274..1e9c50b3e9 100644 --- a/enclave-runtime/Enclave.edl +++ b/enclave-runtime/Enclave.edl @@ -92,7 +92,7 @@ enclave { [out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size); public sgx_status_t get_ecc_vault_pubkey( - [in, size=shard_size] uint8_t* shard, uint32_t shard_size + [in, size=shard_size] uint8_t* shard, uint32_t shard_size, [out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size); public sgx_status_t get_mrenclave( diff --git a/service/src/tests/mocks/enclave_api_mock.rs b/service/src/tests/mocks/enclave_api_mock.rs index 2bcee8a60e..20baa73058 100644 --- a/service/src/tests/mocks/enclave_api_mock.rs +++ b/service/src/tests/mocks/enclave_api_mock.rs @@ -84,6 +84,10 @@ impl EnclaveBase for EnclaveMock { unreachable!() } + fn get_ecc_vault_pubkey(&self) -> EnclaveResult { + unreachable!() + } + fn get_fingerprint(&self) -> EnclaveResult { Ok([1u8; MR_ENCLAVE_SIZE].into()) } From 9911098ec5bdf366fcbd36ca109d2028cbce956a Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 12 Oct 2023 07:54:59 +0200 Subject: [PATCH 07/26] fix transfer call indexes --- app-libs/stf/src/trusted_call.rs | 13 ++++++------- .../node-api/metadata/src/metadata_mocks.rs | 6 +++--- .../node-api/metadata/src/pallet_balances.rs | 12 ++++++------ .../indirect-calls-executor/src/filter_metadata.rs | 9 ++++++--- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/app-libs/stf/src/trusted_call.rs b/app-libs/stf/src/trusted_call.rs index 590c119854..9f104a2b8e 100644 --- a/app-libs/stf/src/trusted_call.rs +++ b/app-libs/stf/src/trusted_call.rs @@ -24,11 +24,14 @@ use std::vec::Vec; use crate::{helpers::ensure_enclave_signer_account, StfError, TrustedOperation}; use codec::{Compact, Decode, Encode}; use frame_support::{ensure, traits::UnfilteredDispatchable}; +#[cfg(feature = "evm")] +use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; pub use ita_sgx_runtime::{Balance, Index}; use ita_sgx_runtime::{Runtime, System}; use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; use itp_node_api_metadata::{ - pallet_enclave_bridge::EnclaveBridgeCallIndexes, pallet_proxy::ProxyCallIndexes, + pallet_balances::BalancesCallIndexes, pallet_enclave_bridge::EnclaveBridgeCallIndexes, + pallet_proxy::ProxyCallIndexes, }; use itp_stf_interface::ExecuteCall; use itp_stf_primitives::types::{AccountId, KeyPair, ShardIdentifier, Signature}; @@ -39,9 +42,6 @@ use sp_io::hashing::blake2_256; use sp_runtime::{traits::Verify, MultiAddress}; use std::{format, prelude::v1::*, sync::Arc}; -#[cfg(feature = "evm")] -use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; - #[cfg(feature = "evm")] use crate::evm_helpers::{create_code_hash, evm_create2_address, evm_create_address}; @@ -256,9 +256,8 @@ where // todo: insert correct vault accountid here let vault_address = Address::from(AccountId::from([0u8; 32])); let vault_transfer_call = OpaqueCall::from_tuple(&( - //node_metadata_repo - // .get_from_metadata(|m| m.transfer_keep_alive_call_indexes())??, - [0u8, 0u8], + node_metadata_repo + .get_from_metadata(|m| m.transfer_keep_alive_call_indexes())??, Address::from(beneficiary), Compact(value), )); diff --git a/core-primitives/node-api/metadata/src/metadata_mocks.rs b/core-primitives/node-api/metadata/src/metadata_mocks.rs index d9cecefc97..8bf47298ec 100644 --- a/core-primitives/node-api/metadata/src/metadata_mocks.rs +++ b/core-primitives/node-api/metadata/src/metadata_mocks.rs @@ -156,15 +156,15 @@ impl ProxyCallIndexes for NodeMetadataMock { } impl BalancesCallIndexes for NodeMetadataMock { - fn transfer_call_index(&self) -> Result<[u8; 2]> { + fn transfer_call_indexes(&self) -> Result<[u8; 2]> { Ok([self.balances_module, self.transfer]) } - fn transfer_keep_alive_call_index(&self) -> Result<[u8; 2]> { + fn transfer_keep_alive_call_indexes(&self) -> Result<[u8; 2]> { Ok([self.balances_module, self.transfer_keep_alive]) } - fn transfer_allow_death_call_index(&self) -> Result<[u8; 2]> { + fn transfer_allow_death_call_indexes(&self) -> Result<[u8; 2]> { Ok([self.balances_module, self.transfer_allow_death]) } } diff --git a/core-primitives/node-api/metadata/src/pallet_balances.rs b/core-primitives/node-api/metadata/src/pallet_balances.rs index 73f3b2e889..9ae88dd742 100644 --- a/core-primitives/node-api/metadata/src/pallet_balances.rs +++ b/core-primitives/node-api/metadata/src/pallet_balances.rs @@ -21,23 +21,23 @@ use crate::{error::Result, NodeMetadata}; const BALANCES: &str = "Balances"; pub trait BalancesCallIndexes { - fn transfer_call_index(&self) -> Result<[u8; 2]>; + fn transfer_call_indexes(&self) -> Result<[u8; 2]>; - fn transfer_keep_alive_call_index(&self) -> Result<[u8; 2]>; + fn transfer_keep_alive_call_indexes(&self) -> Result<[u8; 2]>; - fn transfer_allow_death_call_index(&self) -> Result<[u8; 2]>; + fn transfer_allow_death_call_indexes(&self) -> Result<[u8; 2]>; } impl BalancesCallIndexes for NodeMetadata { - fn transfer_call_index(&self) -> Result<[u8; 2]> { + fn transfer_call_indexes(&self) -> Result<[u8; 2]> { self.call_indexes(BALANCES, "transfer") } - fn transfer_keep_alive_call_index(&self) -> Result<[u8; 2]> { + fn transfer_keep_alive_call_indexes(&self) -> Result<[u8; 2]> { self.call_indexes(BALANCES, "transfer_keep_alive") } - fn transfer_allow_death_call_index(&self) -> Result<[u8; 2]> { + fn transfer_allow_death_call_indexes(&self) -> Result<[u8; 2]> { self.call_indexes(BALANCES, "transfer_allow_death") } } diff --git a/core/parentchain/indirect-calls-executor/src/filter_metadata.rs b/core/parentchain/indirect-calls-executor/src/filter_metadata.rs index dd95b8b0bf..a2adc3c891 100644 --- a/core/parentchain/indirect-calls-executor/src/filter_metadata.rs +++ b/core/parentchain/indirect-calls-executor/src/filter_metadata.rs @@ -174,10 +174,13 @@ where let index = xt.call_index; let call_args = &mut &xt.call_args[..]; log::trace!("[TransferToAliceShieldsFundsFilter] attempting to execute indirect call with index {:?}", index); - if index == metadata.transfer_call_index().ok()? - || index == metadata.transfer_allow_death_call_index().ok()? + if index == metadata.transfer_call_indexes().ok()? + || index == metadata.transfer_keep_alive_call_indexes().ok()? + || index == metadata.transfer_allow_death_call_indexes().ok()? { - log::debug!("found `transfer` or `transfer_allow_death` call."); + log::debug!( + "found `transfer` or `transfer_allow_death` or `transfer_keep_alive` call." + ); let args = decode_and_log_error::(call_args)?; if args.destination == ALICE_ACCOUNT_ID.into() { Some(IndirectCall::TransferToAliceShieldsFunds(args)) From ead36628f0abda4735b08cda775b7d3416a1b4b1 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 12 Oct 2023 08:27:52 +0200 Subject: [PATCH 08/26] unshieldind dummy with real vault account and proxy call --- app-libs/stf/src/trusted_call.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app-libs/stf/src/trusted_call.rs b/app-libs/stf/src/trusted_call.rs index 9f104a2b8e..9d2c9aed50 100644 --- a/app-libs/stf/src/trusted_call.rs +++ b/app-libs/stf/src/trusted_call.rs @@ -33,7 +33,7 @@ use itp_node_api_metadata::{ pallet_balances::BalancesCallIndexes, pallet_enclave_bridge::EnclaveBridgeCallIndexes, pallet_proxy::ProxyCallIndexes, }; -use itp_stf_interface::ExecuteCall; +use itp_stf_interface::{ExecuteCall, SHARD_VAULT_KEY}; use itp_stf_primitives::types::{AccountId, KeyPair, ShardIdentifier, Signature}; use itp_types::{Address, OpaqueCall}; use itp_utils::stringify::account_id_to_string; @@ -44,6 +44,7 @@ use std::{format, prelude::v1::*, sync::Arc}; #[cfg(feature = "evm")] use crate::evm_helpers::{create_code_hash, evm_create2_address, evm_create_address}; +use crate::helpers::get_storage_by_key_hash; #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] #[allow(non_camel_case_types)] @@ -254,7 +255,9 @@ where ))); // todo: the following is a placeholder dummy which will replace the above with #1257 // todo: insert correct vault accountid here - let vault_address = Address::from(AccountId::from([0u8; 32])); + let vault_pubkey: [u8; 32] = get_storage_by_key_hash(SHARD_VAULT_KEY.into()) + .ok_or(StfError::Dispatch("shard vault key hasn't been set".to_string()))?; + let vault_address = Address::from(AccountId::from(vault_pubkey)); let vault_transfer_call = OpaqueCall::from_tuple(&( node_metadata_repo .get_from_metadata(|m| m.transfer_keep_alive_call_indexes())??, From b20d978652574db93da1b781da8e855bb6577edd Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 12 Oct 2023 09:03:52 +0200 Subject: [PATCH 09/26] await vault account creation before registering proxy --- app-libs/stf/src/trusted_call.rs | 1 - core-primitives/ocall-api/src/lib.rs | 1 + core-primitives/test/src/mock/onchain_mock.rs | 1 + .../light-client/src/light_validation.rs | 2 +- enclave-runtime/Enclave.edl | 3 +- enclave-runtime/src/initialization/mod.rs | 5 +-- enclave-runtime/src/ocall/ffi.rs | 1 + enclave-runtime/src/ocall/on_chain_ocall.rs | 2 ++ .../test/mocks/propose_to_import_call_mock.rs | 1 + service/src/ocall_bridge/bridge_api.rs | 1 + .../ocall_bridge/ffi/send_to_parentchain.rs | 7 ++-- .../src/ocall_bridge/worker_on_chain_ocall.rs | 32 ++++++++++++++----- 12 files changed, 42 insertions(+), 15 deletions(-) diff --git a/app-libs/stf/src/trusted_call.rs b/app-libs/stf/src/trusted_call.rs index 9d2c9aed50..d9363b71b8 100644 --- a/app-libs/stf/src/trusted_call.rs +++ b/app-libs/stf/src/trusted_call.rs @@ -254,7 +254,6 @@ where call_hash, ))); // todo: the following is a placeholder dummy which will replace the above with #1257 - // todo: insert correct vault accountid here let vault_pubkey: [u8; 32] = get_storage_by_key_hash(SHARD_VAULT_KEY.into()) .ok_or(StfError::Dispatch("shard vault key hasn't been set".to_string()))?; let vault_address = Address::from(AccountId::from(vault_pubkey)); diff --git a/core-primitives/ocall-api/src/lib.rs b/core-primitives/ocall-api/src/lib.rs index 2bd1ca2104..503a4b5a4c 100644 --- a/core-primitives/ocall-api/src/lib.rs +++ b/core-primitives/ocall-api/src/lib.rs @@ -93,6 +93,7 @@ pub trait EnclaveOnChainOCallApi: Clone + Send + Sync { &self, extrinsics: Vec, parentchain_id: &ParentchainId, + await_each_inclusion: bool, ) -> SgxResult<()>; fn worker_request( diff --git a/core-primitives/test/src/mock/onchain_mock.rs b/core-primitives/test/src/mock/onchain_mock.rs index 1ed4efdc0f..4101636f93 100644 --- a/core-primitives/test/src/mock/onchain_mock.rs +++ b/core-primitives/test/src/mock/onchain_mock.rs @@ -180,6 +180,7 @@ impl EnclaveOnChainOCallApi for OnchainMock { &self, _extrinsics: Vec, _: &ParentchainId, + _: bool, ) -> SgxResult<()> { Ok(()) } diff --git a/core/parentchain/light-client/src/light_validation.rs b/core/parentchain/light-client/src/light_validation.rs index 3eda5c8490..5da9db71d6 100644 --- a/core/parentchain/light-client/src/light_validation.rs +++ b/core/parentchain/light-client/src/light_validation.rs @@ -164,7 +164,7 @@ where { fn send_extrinsics(&mut self, extrinsics: Vec) -> Result<(), Error> { self.ocall_api - .send_to_parentchain(extrinsics, &self.parentchain_id) + .send_to_parentchain(extrinsics, &self.parentchain_id, false) .map_err(|e| { Error::Other( format!("[{:?}] Failed to send extrinsics: {}", self.parentchain_id, e).into(), diff --git a/enclave-runtime/Enclave.edl b/enclave-runtime/Enclave.edl index 1e9c50b3e9..544e988b1a 100644 --- a/enclave-runtime/Enclave.edl +++ b/enclave-runtime/Enclave.edl @@ -250,7 +250,8 @@ enclave { sgx_status_t ocall_send_to_parentchain( [in, size = extrinsics_size] uint8_t * extrinsics, uint32_t extrinsics_size, - [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size, + int await_each_inclusion ); }; }; diff --git a/enclave-runtime/src/initialization/mod.rs b/enclave-runtime/src/initialization/mod.rs index 3490d251df..fd444356d3 100644 --- a/enclave-runtime/src/initialization/mod.rs +++ b/enclave-runtime/src/initialization/mod.rs @@ -343,7 +343,8 @@ pub(crate) fn init_proxied_shard_vault(shard: ShardIdentifier) -> EnclaveResult< info!("vault funding call: 0x{}", hex::encode(call.0.clone())); let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; - ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee); + //this extrinsic must be included in a block before we can move on. otherwise the next will fail + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, true); let nonce_cache = Arc::new(NonceCache::default()); let vault_extrinsics_factory = enclave_extrinsics_factory @@ -364,7 +365,7 @@ pub(crate) fn init_proxied_shard_vault(shard: ShardIdentifier) -> EnclaveResult< info!("add proxy call: 0x{}", hex::encode(call.0.clone())); let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; - ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee); + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false); // xt: delegate proxy authority to its own enclave accountid proxy.add_proxy() (panic if fails) // caveat: must send from vault account. how to sign extrinsics with other keypair? diff --git a/enclave-runtime/src/ocall/ffi.rs b/enclave-runtime/src/ocall/ffi.rs index 4db3bbbba4..acd63ffa46 100644 --- a/enclave-runtime/src/ocall/ffi.rs +++ b/enclave-runtime/src/ocall/ffi.rs @@ -113,6 +113,7 @@ extern "C" { extrinsics_size: u32, parentchain_id: *const u8, parentchain_id_size: u32, + await_each_inclusion: c_int, ) -> sgx_status_t; pub fn ocall_read_ipfs( diff --git a/enclave-runtime/src/ocall/on_chain_ocall.rs b/enclave-runtime/src/ocall/on_chain_ocall.rs index d79c5d5540..e71fb72618 100644 --- a/enclave-runtime/src/ocall/on_chain_ocall.rs +++ b/enclave-runtime/src/ocall/on_chain_ocall.rs @@ -33,6 +33,7 @@ impl EnclaveOnChainOCallApi for OcallApi { &self, extrinsics: Vec, parentchain_id: &ParentchainId, + await_each_inclusion: bool, ) -> SgxResult<()> { let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; let extrinsics_encoded = extrinsics.encode(); @@ -45,6 +46,7 @@ impl EnclaveOnChainOCallApi for OcallApi { extrinsics_encoded.len() as u32, parentchain_id_encoded.as_ptr(), parentchain_id_encoded.len() as u32, + await_each_inclusion.into(), ) }; diff --git a/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs b/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs index ec543b1718..3078bb43c1 100644 --- a/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs +++ b/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs @@ -52,6 +52,7 @@ impl EnclaveOnChainOCallApi for ProposeToImportOCallApi { &self, _extrinsics: Vec, _: &ParentchainId, + _: bool, ) -> SgxResult<()> { Ok(()) } diff --git a/service/src/ocall_bridge/bridge_api.rs b/service/src/ocall_bridge/bridge_api.rs index 9fc3e8eeff..e91ca8409a 100644 --- a/service/src/ocall_bridge/bridge_api.rs +++ b/service/src/ocall_bridge/bridge_api.rs @@ -213,6 +213,7 @@ pub trait WorkerOnChainBridge { &self, extrinsics_encoded: Vec, parentchain_id: Vec, + await_each_inclusion: bool, ) -> OCallBridgeResult<()>; } diff --git a/service/src/ocall_bridge/ffi/send_to_parentchain.rs b/service/src/ocall_bridge/ffi/send_to_parentchain.rs index d9e5220507..ab81f59132 100644 --- a/service/src/ocall_bridge/ffi/send_to_parentchain.rs +++ b/service/src/ocall_bridge/ffi/send_to_parentchain.rs @@ -18,7 +18,7 @@ use crate::ocall_bridge::bridge_api::{Bridge, WorkerOnChainBridge}; use log::*; -use sgx_types::sgx_status_t; +use sgx_types::{c_int, sgx_status_t}; use std::{slice, sync::Arc, vec::Vec}; /// # Safety @@ -30,12 +30,14 @@ pub unsafe extern "C" fn ocall_send_to_parentchain( extrinsics_encoded_size: u32, parentchain_id: *const u8, parentchain_id_size: u32, + await_each_inclusion: c_int, ) -> sgx_status_t { send_to_parentchain( extrinsics_encoded, extrinsics_encoded_size, parentchain_id, parentchain_id_size, + await_each_inclusion.into(), Bridge::get_oc_api(), ) } @@ -45,6 +47,7 @@ fn send_to_parentchain( extrinsics_encoded_size: u32, parentchain_id: *const u8, parentchain_id_size: u32, + await_each_inclusion: bool, oc_api: Arc, ) -> sgx_status_t { let extrinsics_encoded_vec: Vec = unsafe { @@ -54,7 +57,7 @@ fn send_to_parentchain( let parentchain_id: Vec = unsafe { Vec::from(slice::from_raw_parts(parentchain_id, parentchain_id_size as usize)) }; - match oc_api.send_to_parentchain(extrinsics_encoded_vec, parentchain_id) { + match oc_api.send_to_parentchain(extrinsics_encoded_vec, parentchain_id, await_each_inclusion) { Ok(_) => sgx_status_t::SGX_SUCCESS, Err(e) => { error!("send extrinsics_encoded failed: {:?}", e); diff --git a/service/src/ocall_bridge/worker_on_chain_ocall.rs b/service/src/ocall_bridge/worker_on_chain_ocall.rs index 4fec834a7f..27de93a6d4 100644 --- a/service/src/ocall_bridge/worker_on_chain_ocall.rs +++ b/service/src/ocall_bridge/worker_on_chain_ocall.rs @@ -24,7 +24,10 @@ use itp_types::{parentchain::ParentchainId, WorkerRequest, WorkerResponse}; use log::*; use sp_runtime::OpaqueExtrinsic; use std::{sync::Arc, vec::Vec}; -use substrate_api_client::{ac_primitives::serde_impls::StorageKey, GetStorage, SubmitExtrinsic}; +use substrate_api_client::{ + ac_primitives::serde_impls::StorageKey, rpc_api::SubmitAndWatchUntilSuccess, GetStorage, + SubmitAndWatch, SubmitExtrinsic, XtStatus, +}; pub struct WorkerOnChainOCall { integritee_api_factory: Arc, @@ -107,6 +110,7 @@ where &self, extrinsics_encoded: Vec, parentchain_id: Vec, + await_each_inlcusion: bool, ) -> OCallBridgeResult<()> { // TODO: improve error handling, using a mut status is not good design? let mut status: OCallBridgeResult<()> = Ok(()); @@ -131,16 +135,28 @@ where ); let api = self.create_api(parentchain_id)?; for call in extrinsics.into_iter() { - if let Err(e) = api.submit_opaque_extrinsic(&call.encode().into()) { - error!( - "Could not send extrinsic to node: {:?}, error: {:?}", - serde_json::to_string(&call), - e - ); + if await_each_inlcusion { + if let Err(e) = api.submit_and_watch_opaque_extrinsic_until( + &call.encode().into(), + XtStatus::InBlock, + ) { + error!( + "Could not send extrinsic to node: {:?}, error: {:?}", + serde_json::to_string(&call), + e + ); + } + } else { + if let Err(e) = api.submit_opaque_extrinsic(&call.encode().into()) { + error!( + "Could not send extrinsic to node: {:?}, error: {:?}", + serde_json::to_string(&call), + e + ); + } } } } - status } } From 4524b9f466d1d5ebbacffb990c938e2469c66665 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 12 Oct 2023 12:53:08 +0200 Subject: [PATCH 10/26] proxied unshielding call encodes correctly and would be executed if there were funds --- Cargo.lock | 1 + app-libs/stf/src/trusted_call.rs | 12 ++++++++---- .../node-api/metadata/src/pallet_proxy.rs | 2 ++ core-primitives/stf-executor/Cargo.toml | 2 ++ core-primitives/stf-executor/src/executor.rs | 3 +++ enclave-runtime/Cargo.lock | 1 + enclave-runtime/src/initialization/mod.rs | 8 ++++++-- service/src/ocall_bridge/ffi/send_to_parentchain.rs | 2 +- service/src/ocall_bridge/worker_on_chain_ocall.rs | 4 ++-- 9 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9bd310699b..fbcda65eba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3692,6 +3692,7 @@ dependencies = [ name = "itp-stf-executor" version = "0.9.0" dependencies = [ + "hex", "ita-stf", "itc-parentchain-test", "itp-node-api", diff --git a/app-libs/stf/src/trusted_call.rs b/app-libs/stf/src/trusted_call.rs index d9363b71b8..7625e53e1a 100644 --- a/app-libs/stf/src/trusted_call.rs +++ b/app-libs/stf/src/trusted_call.rs @@ -35,7 +35,7 @@ use itp_node_api_metadata::{ }; use itp_stf_interface::{ExecuteCall, SHARD_VAULT_KEY}; use itp_stf_primitives::types::{AccountId, KeyPair, ShardIdentifier, Signature}; -use itp_types::{Address, OpaqueCall}; +use itp_types::{parentchain::ProxyType, Address, OpaqueCall}; use itp_utils::stringify::account_id_to_string; use log::*; use sp_io::hashing::blake2_256; @@ -253,7 +253,9 @@ where value, call_hash, ))); - // todo: the following is a placeholder dummy which will replace the above with #1257 + // todo: the following is a placeholder dummy which will replace the above with #1257. + // the extrinsic will be sent and potentially deplete the vault at the current state which + // is nothing to worry about before we solve mentioned issue. let vault_pubkey: [u8; 32] = get_storage_by_key_hash(SHARD_VAULT_KEY.into()) .ok_or(StfError::Dispatch("shard vault key hasn't been set".to_string()))?; let vault_address = Address::from(AccountId::from(vault_pubkey)); @@ -263,11 +265,13 @@ where Address::from(beneficiary), Compact(value), )); - calls.push(OpaqueCall::from_tuple(&( + let proxy_call = OpaqueCall::from_tuple(&( node_metadata_repo.get_from_metadata(|m| m.proxy_call_indexes())??, vault_address, + None::, vault_transfer_call, - ))); + )); + calls.push(proxy_call); Ok(()) }, TrustedCall::balance_shield(enclave_account, who, value) => { diff --git a/core-primitives/node-api/metadata/src/pallet_proxy.rs b/core-primitives/node-api/metadata/src/pallet_proxy.rs index a0106457b0..6a7aa14b08 100644 --- a/core-primitives/node-api/metadata/src/pallet_proxy.rs +++ b/core-primitives/node-api/metadata/src/pallet_proxy.rs @@ -19,6 +19,8 @@ use crate::{error::Result, NodeMetadata}; /// Pallet name: const PROXY: &str = "Proxy"; +/// the deposit needed to register up to 20 proxies in native parentchain token +pub const PROXY_DEPOSIT: u128 = 21_000_000_000_000; pub trait ProxyCallIndexes { fn add_proxy_call_indexes(&self) -> Result<[u8; 2]>; diff --git a/core-primitives/stf-executor/Cargo.toml b/core-primitives/stf-executor/Cargo.toml index ee844db96f..da91248f70 100644 --- a/core-primitives/stf-executor/Cargo.toml +++ b/core-primitives/stf-executor/Cargo.toml @@ -5,6 +5,8 @@ authors = ["Integritee AG "] edition = "2021" [dependencies] +hex = { version = "0.4.3", default-features = false, features = ["alloc"] } + # sgx dependencies sgx-crypto-helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", package = "sgx_crypto_helper", default-features = false, optional = true } sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true, features = ["untrusted_time"] } diff --git a/core-primitives/stf-executor/src/executor.rs b/core-primitives/stf-executor/src/executor.rs index 3c5f53afb9..a40eb84445 100644 --- a/core-primitives/stf-executor/src/executor.rs +++ b/core-primitives/stf-executor/src/executor.rs @@ -127,6 +127,9 @@ where state.prune_state_diff(); } + for call in extrinsic_call_backs.clone() { + trace!("trusted_call wants to send encoded call: 0x{}", hex::encode(call.encode())); + } Ok(ExecutedOperation::success(operation_hash, top_or_hash, extrinsic_call_backs)) } } diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index f38d112465..846907e5c6 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -2185,6 +2185,7 @@ dependencies = [ name = "itp-stf-executor" version = "0.9.0" dependencies = [ + "hex", "ita-stf", "itc-parentchain-test", "itp-node-api", diff --git a/enclave-runtime/src/initialization/mod.rs b/enclave-runtime/src/initialization/mod.rs index fd444356d3..2b4d38c4e9 100644 --- a/enclave-runtime/src/initialization/mod.rs +++ b/enclave-runtime/src/initialization/mod.rs @@ -63,7 +63,10 @@ use itp_component_container::{ComponentGetter, ComponentInitializer}; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::{ api_client::{PairSignature, StaticExtrinsicSigner}, - metadata::provider::{AccessNodeMetadata, Error as MetadataProviderError}, + metadata::{ + pallet_proxy::PROXY_DEPOSIT, + provider::{AccessNodeMetadata, Error as MetadataProviderError}, + }, }; use itp_nonce_cache::NonceCache; use itp_ocall_api::EnclaveOnChainOCallApi; @@ -337,7 +340,7 @@ pub(crate) fn init_proxied_shard_vault(shard: ShardIdentifier) -> EnclaveResult< let call = OpaqueCall::from_tuple(&( call_ids, Address::from(AccountId::from(vault.public().0)), - Compact(Balance::from(20_000_000_000_000u128)), + Compact(Balance::from(PROXY_DEPOSIT)), )); info!("vault funding call: 0x{}", hex::encode(call.0.clone())); @@ -346,6 +349,7 @@ pub(crate) fn init_proxied_shard_vault(shard: ShardIdentifier) -> EnclaveResult< //this extrinsic must be included in a block before we can move on. otherwise the next will fail ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, true); + // we are assuming nonce=0 here. let nonce_cache = Arc::new(NonceCache::default()); let vault_extrinsics_factory = enclave_extrinsics_factory .with_signer(StaticExtrinsicSigner::<_, PairSignature>::new(vault), nonce_cache); diff --git a/service/src/ocall_bridge/ffi/send_to_parentchain.rs b/service/src/ocall_bridge/ffi/send_to_parentchain.rs index ab81f59132..d7e524a254 100644 --- a/service/src/ocall_bridge/ffi/send_to_parentchain.rs +++ b/service/src/ocall_bridge/ffi/send_to_parentchain.rs @@ -37,7 +37,7 @@ pub unsafe extern "C" fn ocall_send_to_parentchain( extrinsics_encoded_size, parentchain_id, parentchain_id_size, - await_each_inclusion.into(), + await_each_inclusion == 1, Bridge::get_oc_api(), ) } diff --git a/service/src/ocall_bridge/worker_on_chain_ocall.rs b/service/src/ocall_bridge/worker_on_chain_ocall.rs index 27de93a6d4..c1481288ee 100644 --- a/service/src/ocall_bridge/worker_on_chain_ocall.rs +++ b/service/src/ocall_bridge/worker_on_chain_ocall.rs @@ -129,9 +129,9 @@ where if !extrinsics.is_empty() { let parentchain_id = ParentchainId::decode(&mut parentchain_id.as_slice())?; debug!( - "Enclave wants to send {} extrinsics to parentchain: {:?}", + "Enclave wants to send {} extrinsics to parentchain: {:?}. await each inclusion: {:?}", extrinsics.len(), - parentchain_id + parentchain_id, await_each_inlcusion ); let api = self.create_api(parentchain_id)?; for call in extrinsics.into_iter() { From 6587f1bed11ad8604ccf78c0da72a6fd8e36e330 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 12 Oct 2023 15:10:04 +0200 Subject: [PATCH 11/26] start MU_RA doc diagrams and refactor namings for improved readability --- enclave-runtime/src/tls_ra/README.md | 22 +++++++++++++++++++++ enclave-runtime/src/tls_ra/tls_ra_client.rs | 17 +++++++++------- enclave-runtime/src/tls_ra/tls_ra_server.rs | 1 + 3 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 enclave-runtime/src/tls_ra/README.md diff --git a/enclave-runtime/src/tls_ra/README.md b/enclave-runtime/src/tls_ra/README.md new file mode 100644 index 0000000000..9c2655f04d --- /dev/null +++ b/enclave-runtime/src/tls_ra/README.md @@ -0,0 +1,22 @@ +# provisioning + +each worker runs a provisioning server for other workers of the same MRENCLAVE and shard to get recent stf state and secrets from. + +Light client storage can also be provisioned to avoid re-synching the entire parentchains with each worker + +```mermaid +sequenceDiagram +participant server +participant client +server ->> server: generate shielding & state encryption key +server ->> server: init_shard & sync parentchains +client ->> server: enclave_request_state_provisioning +activate client +client ->> client: qe_get_target_info + + + +deactivate client + + +``` diff --git a/enclave-runtime/src/tls_ra/tls_ra_client.rs b/enclave-runtime/src/tls_ra/tls_ra_client.rs index 630f8877d3..4e732f64d2 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_client.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_client.rs @@ -73,16 +73,18 @@ where /// /// We trust here that the server sends us the correct data, as /// we do not have any way to test it. - fn read_shard(&mut self) -> EnclaveResult<()> { - debug!("read_shard called, about to call self.write_shard()."); - self.write_shard()?; - debug!("self.write_shard() succeeded."); + fn obtain_provisioning_for_shard(&mut self) -> EnclaveResult<()> { + debug!( + "obtain_provisioning_for_shard called, about to call self.send_provisioning_request()." + ); + self.send_provisioning_request()?; + debug!("self.send_provisioning_request() succeeded."); self.read_and_seal_all() } /// Send the shard of the state we want to receive to the provisioning server. - fn write_shard(&mut self) -> EnclaveResult<()> { - debug!("self.write_shard() called."); + fn send_provisioning_request(&mut self) -> EnclaveResult<()> { + debug!("self.send_provisioning_request() called."); self.tls_stream.write_all(self.shard.as_bytes())?; debug!("write_all succeeded."); Ok(()) @@ -253,7 +255,7 @@ pub(crate) fn request_state_provisioning_internal( @@ -268,6 +270,7 @@ fn tls_client_config( #[cfg(feature = "dcap")] let attestation_type = RemoteAttestationType::Dcap; + // report will be signed with enclave ed25519 signing key let (key_der, cert_der) = create_ra_report_and_signature( skip_ra, attestation_type, diff --git a/enclave-runtime/src/tls_ra/tls_ra_server.rs b/enclave-runtime/src/tls_ra/tls_ra_server.rs index e47ca50ed8..a80e1abbcf 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_server.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -279,6 +279,7 @@ fn tls_server_config( #[cfg(feature = "dcap")] let attestation_type = RemoteAttestationType::Dcap; + // report will be signed with enclave ed25519 signing key let (key_der, cert_der) = create_ra_report_and_signature( skip_ra, attestation_type, From d5ce0c7f01a2c3372332900766a66230609ee15a Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 12 Oct 2023 17:52:30 +0200 Subject: [PATCH 12/26] refactoring MU RA functions for better readability. try to extract client pubkey form cert. builds but fails --- .../attestation-handler/src/cert.rs | 26 +++++++++ enclave-runtime/Cargo.lock | 2 +- enclave-runtime/src/tls_ra/tls_ra_client.rs | 3 +- enclave-runtime/src/tls_ra/tls_ra_server.rs | 53 ++++++++++++++----- 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/core-primitives/attestation-handler/src/cert.rs b/core-primitives/attestation-handler/src/cert.rs index 99c0d8529b..7d1a2d6064 100644 --- a/core-primitives/attestation-handler/src/cert.rs +++ b/core-primitives/attestation-handler/src/cert.rs @@ -234,6 +234,31 @@ pub fn percent_decode(orig: String) -> EnclaveResult { Ok(ret) } +pub fn parse_cert_issuer(cert_der: &[u8]) -> SgxResult> { + // Before we reach here, Webpki already verified the cert is properly signed + + // Search for Public Key prime256v1 OID + let prime256v1_oid = &[0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]; + let mut offset = cert_der + .windows(prime256v1_oid.len()) + .position(|window| window == prime256v1_oid) + .ok_or(sgx_status_t::SGX_ERROR_UNEXPECTED)?; + offset += 11; // 10 + TAG (0x03) + + // Obtain Public Key length + let mut len = cert_der[offset] as usize; + if len > 0x80 { + len = (cert_der[offset + 1] as usize) * 0x100 + (cert_der[offset + 2] as usize); + offset += 2; + } + + // Obtain Public Key + offset += 1; + let pub_k = cert_der[offset + 2..offset + len].to_vec(); // skip "00 04" + + Ok(pub_k) +} + // FIXME: This code is redundant with the host call of the integritee-node pub fn verify_mra_cert( cert_der: &[u8], @@ -346,6 +371,7 @@ where verify_attn_report(attn_report_raw, pub_k, attestation_ocall) } else { // TODO Refactor state provisioning to not use MURA #1385 + // TODO DCAP is currently just passed through! SECURITY!!! Ok(()) } } diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index 846907e5c6..29dd4bdf15 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -4885,7 +4885,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "digest 0.10.7", "static_assertions", ] diff --git a/enclave-runtime/src/tls_ra/tls_ra_client.rs b/enclave-runtime/src/tls_ra/tls_ra_client.rs index 4e732f64d2..b83d3ab5e0 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_client.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_client.rs @@ -270,7 +270,7 @@ fn tls_client_config( #[cfg(feature = "dcap")] let attestation_type = RemoteAttestationType::Dcap; - // report will be signed with enclave ed25519 signing key + // report will be signed with client enclave ed25519 signing key let (key_der, cert_der) = create_ra_report_and_signature( skip_ra, attestation_type, @@ -285,6 +285,7 @@ fn tls_client_config( let privkey = rustls::PrivateKey(key_der); cfg.set_single_client_cert(certs, privkey).unwrap(); + // ServerAuth will perform MU RA as part of authentication process cfg.dangerous() .set_certificate_verifier(Arc::new(ServerAuth::new(true, skip_ra, ocall_api))); cfg.versions.clear(); diff --git a/enclave-runtime/src/tls_ra/tls_ra_server.rs b/enclave-runtime/src/tls_ra/tls_ra_server.rs index a80e1abbcf..e8ae807997 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_server.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -29,13 +29,13 @@ use crate::{ tls_ra::seal_handler::UnsealStateAndKeys, GLOBAL_STATE_HANDLER_COMPONENT, }; -use itp_attestation_handler::RemoteAttestationType; +use itp_attestation_handler::{cert::parse_cert_issuer, RemoteAttestationType}; use itp_component_container::ComponentGetter; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; use itp_types::ShardIdentifier; use log::*; -use rustls::{ServerConfig, ServerSession, StreamOwned}; +use rustls::{ServerConfig, ServerSession, Session, StreamOwned}; use sgx_types::*; use std::{ backtrace::{self, PrintFormat}, @@ -82,25 +82,29 @@ where } /// Sends all relevant data of the specific shard to the client. - fn write_shard(&mut self) -> EnclaveResult<()> { - println!(" [Enclave] (MU-RA-Server) write_shard, calling read_shard()"); - let shard = self.read_shard()?; - println!(" [Enclave] (MU-RA-Server) write_shard, read_shard() OK"); - println!(" [Enclave] (MU-RA-Server) write_shard, write_all()"); - self.write_all(&shard) + fn handle_shard_request_from_client(&mut self) -> EnclaveResult<()> { + println!( + " [Enclave] (MU-RA-Server) handle_shard_request_from_client, calling read_shard()" + ); + let shard = self.await_shard_request_from_client()?; + println!(" [Enclave] (MU-RA-Server) handle_shard_request_from_client, await_shard_request_from_client() OK"); + println!(" [Enclave] (MU-RA-Server) handle_shard_request_from_client, write_all()"); + self.write_provisioning_payloads(&shard) } /// Read the shard of the state the client wants to receive. - fn read_shard(&mut self) -> EnclaveResult { + fn await_shard_request_from_client(&mut self) -> EnclaveResult { let mut shard_holder = ShardIdentifier::default(); let shard = shard_holder.as_fixed_bytes_mut(); - println!(" [Enclave] (MU-RA-Server) read_shard, calling read_exact()"); + println!( + " [Enclave] (MU-RA-Server) await_shard_request_from_client, calling read_exact()" + ); self.tls_stream.read_exact(shard)?; Ok(shard.into()) } /// Sends all relevant data to the client. - fn write_all(&mut self, shard: &ShardIdentifier) -> EnclaveResult<()> { + fn write_provisioning_payloads(&mut self, shard: &ShardIdentifier) -> EnclaveResult<()> { debug!("Provisioning is set to: {:?}", self.provisioning_payload); match self.provisioning_payload { ProvisioningPayload::Everything => { @@ -248,14 +252,34 @@ pub(crate) fn run_state_provisioning_server_internal< skip_ra == 1, )?; let (server_session, tcp_stream) = tls_server_session_stream(socket_fd, server_config)?; + + let client_signer = if let Some(cert_chain) = server_session.get_peer_certificates() { + if !cert_chain.is_empty() { + // Assuming the leaf certificate is the first in the list + parse_cert_issuer(&cert_chain[0].0)? + } else { + return Err(EnclaveError::Other("no certificates found".into())) + } + } else { + return Err(EnclaveError::Other("get peer certificates failed".into())) + }; + info!("client signer (issuer) is: 0x{}", hex::encode(client_signer.clone())); + + // todo: verify client signer belongs to a registered enclave on integritee network with a + // matching or whitelisted MRENCLAVE as replacement for MU RA #1385 + let provisioning = ProvisioningPayload::from(WorkerModeProvider::worker_mode()); let mut server = TlsServer::new(StreamOwned::new(server_session, tcp_stream), seal_handler, provisioning); println!(" [Enclave] (MU-RA-Server) MU-RA successful sending keys"); - println!(" [Enclave] (MU-RA-Server) MU-RA successful, calling write_shard()"); - server.write_shard() + println!( + " [Enclave] (MU-RA-Server) MU-RA successful, calling handle_shard_request_from_client()" + ); + server.handle_shard_request_from_client() + + // todo! add client account as a proxy to shard vault account } fn tls_server_session_stream( @@ -279,7 +303,7 @@ fn tls_server_config( #[cfg(feature = "dcap")] let attestation_type = RemoteAttestationType::Dcap; - // report will be signed with enclave ed25519 signing key + // report will be signed with server enclave ed25519 signing key let (key_der, cert_der) = create_ra_report_and_signature( skip_ra, attestation_type, @@ -288,6 +312,7 @@ fn tls_server_config( quote_size, )?; + // ClientAuth will perform MU RA as part of authentication process let mut cfg = rustls::ServerConfig::new(Arc::new(ClientAuth::new(true, skip_ra, ocall_api))); let certs = vec![rustls::Certificate(cert_der)]; let privkey = rustls::PrivateKey(key_der); From cd3562df492ee1e881a1357daefa29ace368d039 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 12 Oct 2023 18:23:13 +0200 Subject: [PATCH 13/26] logging pubkey of counterparty now during MU RA. but seems skip_ra won't behave as expected. punkeys don't match and fill all 64 bytes --- enclave-runtime/src/tls_ra/authentication.rs | 6 +++++- enclave-runtime/src/tls_ra/tls_ra_server.rs | 12 ------------ 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/enclave-runtime/src/tls_ra/authentication.rs b/enclave-runtime/src/tls_ra/authentication.rs index d1f9633497..ab84a76e71 100644 --- a/enclave-runtime/src/tls_ra/authentication.rs +++ b/enclave-runtime/src/tls_ra/authentication.rs @@ -16,7 +16,6 @@ */ //! Remote attestation certificate authentication of server and client - use itp_attestation_handler::cert; use itp_ocall_api::EnclaveAttestationOCallApi; use log::*; @@ -52,6 +51,9 @@ where _sni: Option<&DNSName>, ) -> Result { debug!("client cert: {:?}", certs); + let issuer = cert::parse_cert_issuer(&certs[0].0).unwrap(); + info!("client signer (issuer) is: 0x{}", hex::encode(issuer.clone())); + // This call will automatically verify cert is properly signed if self.skip_ra { warn!("Skip verifying ra-report"); @@ -104,6 +106,8 @@ where _ocsp: &[u8], ) -> Result { debug!("server cert: {:?}", certs); + let issuer = cert::parse_cert_issuer(&certs[0].0).unwrap(); + info!("server signer (issuer) is: 0x{}", hex::encode(issuer.clone())); if self.skip_ra { warn!("Skip verifying ra-report"); diff --git a/enclave-runtime/src/tls_ra/tls_ra_server.rs b/enclave-runtime/src/tls_ra/tls_ra_server.rs index e8ae807997..5f1e9ca9d0 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_server.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -253,18 +253,6 @@ pub(crate) fn run_state_provisioning_server_internal< )?; let (server_session, tcp_stream) = tls_server_session_stream(socket_fd, server_config)?; - let client_signer = if let Some(cert_chain) = server_session.get_peer_certificates() { - if !cert_chain.is_empty() { - // Assuming the leaf certificate is the first in the list - parse_cert_issuer(&cert_chain[0].0)? - } else { - return Err(EnclaveError::Other("no certificates found".into())) - } - } else { - return Err(EnclaveError::Other("get peer certificates failed".into())) - }; - info!("client signer (issuer) is: 0x{}", hex::encode(client_signer.clone())); - // todo: verify client signer belongs to a registered enclave on integritee network with a // matching or whitelisted MRENCLAVE as replacement for MU RA #1385 From 36bdc5c592b82ddc374423361d5309563ac121da Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Fri, 13 Oct 2023 10:11:00 +0200 Subject: [PATCH 14/26] add client account to MU RA request --- .../src/attestation_handler.rs | 2 ++ enclave-runtime/src/tls_ra/mod.rs | 8 +++++ enclave-runtime/src/tls_ra/tests.rs | 4 +++ enclave-runtime/src/tls_ra/tls_ra_client.rs | 35 ++++++++++++++----- enclave-runtime/src/tls_ra/tls_ra_server.rs | 32 ++++++++++------- 5 files changed, 60 insertions(+), 21 deletions(-) diff --git a/core-primitives/attestation-handler/src/attestation_handler.rs b/core-primitives/attestation-handler/src/attestation_handler.rs index 91bfc77f3a..59e4988be2 100644 --- a/core-primitives/attestation-handler/src/attestation_handler.rs +++ b/core-primitives/attestation-handler/src/attestation_handler.rs @@ -279,6 +279,8 @@ where let _result = ecc_handle.open(); let (prv_k, pub_k) = ecc_handle.create_key_pair()?; info!("Enclave Attestation] Generated ephemeral ECDSA keypair:"); + debug!(" pubkey X is {:02x}", pub_k.gx.iter().format("")); + debug!(" pubkey Y is {:02x}", pub_k.gy.iter().format("")); let qe_quote = if !skip_ra { let qe_quote = match self.retrieve_qe_dcap_quote( diff --git a/enclave-runtime/src/tls_ra/mod.rs b/enclave-runtime/src/tls_ra/mod.rs index 90724cdfe5..07474f3f8b 100644 --- a/enclave-runtime/src/tls_ra/mod.rs +++ b/enclave-runtime/src/tls_ra/mod.rs @@ -19,6 +19,7 @@ //! including the remote attestation and tls / tcp connection part. use codec::{Decode, Encode, MaxEncodedLen}; +use itp_types::{AccountId, ShardIdentifier}; mod authentication; pub mod seal_handler; @@ -71,3 +72,10 @@ impl Opcode { (self as u8).to_be_bytes() } } + +/// The data structure to be sent by the client to request provisioning +#[derive(Clone, Debug, Eq, PartialEq, Decode, Encode, MaxEncodedLen)] +pub struct ClientProvisioningRequest { + pub shard: ShardIdentifier, + pub account: AccountId, +} diff --git a/enclave-runtime/src/tls_ra/tests.rs b/enclave-runtime/src/tls_ra/tests.rs index beae945656..37b69c64f7 100644 --- a/enclave-runtime/src/tls_ra/tests.rs +++ b/enclave-runtime/src/tls_ra/tests.rs @@ -72,6 +72,7 @@ fn server_addr(port: u16) -> String { pub fn test_tls_ra_server_client_networking() { let shard = ShardIdentifier::default(); + let client_account = AccountId::from([42; 32]); let shielding_key_encoded = vec![1, 2, 3]; let state_key_encoded = vec![5, 2, 3, 7]; let state_encoded = Vec::from([1u8; 26000]); // Have a decently sized state, so read() must be called multiple times. @@ -118,6 +119,7 @@ pub fn test_tls_ra_server_client_networking() { shard, SKIP_RA, client_seal_handler.clone(), + client_account, ); // Ensure server thread has finished. @@ -139,6 +141,7 @@ pub fn test_tls_ra_server_client_networking() { // Test state and key provisioning with 'real' data structures. pub fn test_state_and_key_provisioning() { + let client_account = AccountId::from([42; 32]); let state_key = Aes::new([3u8; 16], [0u8; 16]); let shielding_key = Rsa3072KeyPair::new().unwrap(); let initialized_state = EnclaveStf::init_state(AccountId::new([1u8; 32])); @@ -168,6 +171,7 @@ pub fn test_state_and_key_provisioning() { shard, SKIP_RA, client_seal_handler, + client_account, ); // Ensure server thread has finished. diff --git a/enclave-runtime/src/tls_ra/tls_ra_client.rs b/enclave-runtime/src/tls_ra/tls_ra_client.rs index b83d3ab5e0..0fac6f3890 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_client.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_client.rs @@ -26,13 +26,15 @@ use crate::{ GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, }, ocall::OcallApi, - tls_ra::seal_handler::SealStateAndKeys, - GLOBAL_STATE_HANDLER_COMPONENT, + tls_ra::{seal_handler::SealStateAndKeys, ClientProvisioningRequest}, + GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, }; +use codec::Encode; use itp_attestation_handler::{RemoteAttestationType, DEV_HOSTNAME}; use itp_component_container::ComponentGetter; use itp_ocall_api::EnclaveAttestationOCallApi; -use itp_types::ShardIdentifier; +use itp_sgx_crypto::key_repository::AccessPubkey; +use itp_types::{AccountId, ShardIdentifier}; use log::*; use rustls::{ClientConfig, ClientSession, Stream}; use sgx_types::*; @@ -44,7 +46,6 @@ use std::{ sync::Arc, vec::Vec, }; - /// Client part of the TCP-level connection and the underlying TLS-level session. /// /// Includes a seal handler, which handles the storage part of the received data. @@ -73,19 +74,20 @@ where /// /// We trust here that the server sends us the correct data, as /// we do not have any way to test it. - fn obtain_provisioning_for_shard(&mut self) -> EnclaveResult<()> { + fn obtain_provisioning_for_shard(&mut self, account: AccountId) -> EnclaveResult<()> { debug!( "obtain_provisioning_for_shard called, about to call self.send_provisioning_request()." ); - self.send_provisioning_request()?; + self.send_provisioning_request(account)?; debug!("self.send_provisioning_request() succeeded."); self.read_and_seal_all() } /// Send the shard of the state we want to receive to the provisioning server. - fn send_provisioning_request(&mut self) -> EnclaveResult<()> { + fn send_provisioning_request(&mut self, account: AccountId) -> EnclaveResult<()> { debug!("self.send_provisioning_request() called."); - self.tls_stream.write_all(self.shard.as_bytes())?; + self.tls_stream + .write_all(&ClientProvisioningRequest { shard: self.shard, account }.encode())?; debug!("write_all succeeded."); Ok(()) } @@ -210,6 +212,19 @@ pub unsafe extern "C" fn request_state_provisioning( light_client_seal, ); + let signing_key_repository = match GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let client_account = match signing_key_repository.retrieve_pubkey() { + Ok(s) => AccountId::from(s), + Err(e) => return e.into(), + }; + if let Err(e) = request_state_provisioning_internal( socket_fd, sign_type, @@ -218,6 +233,7 @@ pub unsafe extern "C" fn request_state_provisioning( shard, skip_ra, seal_handler, + client_account, ) { error!("Failed to sync state due to: {:?}", e); return e.into() @@ -235,6 +251,7 @@ pub(crate) fn request_state_provisioning_internal EnclaveResult<()> { debug!("Client config generate..."); let client_config = tls_client_config( @@ -255,7 +272,7 @@ pub(crate) fn request_state_provisioning_internal( diff --git a/enclave-runtime/src/tls_ra/tls_ra_server.rs b/enclave-runtime/src/tls_ra/tls_ra_server.rs index 5f1e9ca9d0..6e5c03ed58 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_server.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -17,7 +17,7 @@ //! Implementation of the server part of the state provisioning. -use super::{authentication::ClientAuth, Opcode, TcpHeader}; +use super::{authentication::ClientAuth, ClientProvisioningRequest, Opcode, TcpHeader}; use crate::{ attestation::create_ra_report_and_signature, error::{Error as EnclaveError, Result as EnclaveResult}, @@ -29,11 +29,12 @@ use crate::{ tls_ra::seal_handler::UnsealStateAndKeys, GLOBAL_STATE_HANDLER_COMPONENT, }; +use codec::Decode; use itp_attestation_handler::{cert::parse_cert_issuer, RemoteAttestationType}; use itp_component_container::ComponentGetter; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; -use itp_types::ShardIdentifier; +use itp_types::{AccountId, ShardIdentifier}; use log::*; use rustls::{ServerConfig, ServerSession, Session, StreamOwned}; use sgx_types::*; @@ -82,25 +83,29 @@ where } /// Sends all relevant data of the specific shard to the client. - fn handle_shard_request_from_client(&mut self) -> EnclaveResult<()> { + fn handle_shard_request_from_client(&mut self) -> EnclaveResult { println!( " [Enclave] (MU-RA-Server) handle_shard_request_from_client, calling read_shard()" ); - let shard = self.await_shard_request_from_client()?; + let request = self.await_shard_request_from_client()?; println!(" [Enclave] (MU-RA-Server) handle_shard_request_from_client, await_shard_request_from_client() OK"); println!(" [Enclave] (MU-RA-Server) handle_shard_request_from_client, write_all()"); - self.write_provisioning_payloads(&shard) + self.write_provisioning_payloads(&request.shard)?; + Ok(request.account) } /// Read the shard of the state the client wants to receive. - fn await_shard_request_from_client(&mut self) -> EnclaveResult { + fn await_shard_request_from_client(&mut self) -> EnclaveResult { let mut shard_holder = ShardIdentifier::default(); let shard = shard_holder.as_fixed_bytes_mut(); + let mut request = [0u8; std::mem::size_of::()]; println!( " [Enclave] (MU-RA-Server) await_shard_request_from_client, calling read_exact()" ); - self.tls_stream.read_exact(shard)?; - Ok(shard.into()) + self.tls_stream.read_exact(&mut request)?; + let request: ClientProvisioningRequest = Decode::decode(&mut request.as_slice()) + .expect("matching byte size can't fail to decode"); + Ok(request) } /// Sends all relevant data to the client. @@ -253,21 +258,24 @@ pub(crate) fn run_state_provisioning_server_internal< )?; let (server_session, tcp_stream) = tls_server_session_stream(socket_fd, server_config)?; - // todo: verify client signer belongs to a registered enclave on integritee network with a - // matching or whitelisted MRENCLAVE as replacement for MU RA #1385 - let provisioning = ProvisioningPayload::from(WorkerModeProvider::worker_mode()); let mut server = TlsServer::new(StreamOwned::new(server_session, tcp_stream), seal_handler, provisioning); + // todo: verify client signer belongs to a registered enclave on integritee network with a + // matching or whitelisted MRENCLAVE as replacement for MU RA #1385 + println!(" [Enclave] (MU-RA-Server) MU-RA successful sending keys"); println!( " [Enclave] (MU-RA-Server) MU-RA successful, calling handle_shard_request_from_client()" ); - server.handle_shard_request_from_client() + let client_account = server.handle_shard_request_from_client()?; + info!("will make client account 0x{} a proxy of vault", hex::encode(client_account.clone())); // todo! add client account as a proxy to shard vault account + + Ok(()) } fn tls_server_session_stream( From b5da3a216df3013a49a6cee0d9a1a470f6356476 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Fri, 13 Oct 2023 11:13:08 +0200 Subject: [PATCH 15/26] starting to modularize vault logic --- enclave-runtime/src/initialization/mod.rs | 72 ------ enclave-runtime/src/lib.rs | 49 +--- enclave-runtime/src/shard_vault.rs | 291 ++++++++++++++++++++++ 3 files changed, 293 insertions(+), 119 deletions(-) create mode 100644 enclave-runtime/src/shard_vault.rs diff --git a/enclave-runtime/src/initialization/mod.rs b/enclave-runtime/src/initialization/mod.rs index 2b4d38c4e9..a9b1e4a9c1 100644 --- a/enclave-runtime/src/initialization/mod.rs +++ b/enclave-runtime/src/initialization/mod.rs @@ -307,78 +307,6 @@ pub(crate) fn init_shard(shard: ShardIdentifier) -> EnclaveResult<()> { Ok(()) } -pub(crate) fn init_proxied_shard_vault(shard: ShardIdentifier) -> EnclaveResult<()> { - let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; - if !state_handler.shard_exists(&shard).unwrap() { - return Err(Error::Other("shard not initialized".into())) - }; - - let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; - let enclave_signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; - let enclave_extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; - let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; - let vault = enclave_signer - .derive(vec![DeriveJunction::hard(shard.encode())].into_iter(), None) - .map_err(|e| Error::Other("failed to derive shard vault keypair".into()))? - .0; - - info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0.clone())); - - let (state_lock, mut state) = state_handler.load_for_mutation(&shard)?; - state.state.insert(SHARD_VAULT_KEY.into(), vault.public().0.to_vec()); - state_handler.write_after_mutation(state, state_lock, &shard)?; - // todo! - // parentchain-query: if shard vault not yet existing or self not proxy: - - // xt: send funds from enclave account to new vault account (panic if not enough funds) - - info!("send existential funds from enclave account to vault account"); - let call_ids = node_metadata_repo - .get_from_metadata(|m| m.call_indexes("Balances", "transfer_keep_alive"))? - .map_err(MetadataProviderError::MetadataError)?; - - let call = OpaqueCall::from_tuple(&( - call_ids, - Address::from(AccountId::from(vault.public().0)), - Compact(Balance::from(PROXY_DEPOSIT)), - )); - - info!("vault funding call: 0x{}", hex::encode(call.0.clone())); - let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; - - //this extrinsic must be included in a block before we can move on. otherwise the next will fail - ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, true); - - // we are assuming nonce=0 here. - let nonce_cache = Arc::new(NonceCache::default()); - let vault_extrinsics_factory = enclave_extrinsics_factory - .with_signer(StaticExtrinsicSigner::<_, PairSignature>::new(vault), nonce_cache); - - info!("register enclave signer as proxy for shard vault"); - let call_ids = node_metadata_repo - .get_from_metadata(|m| m.call_indexes("Proxy", "add_proxy"))? - .map_err(MetadataProviderError::MetadataError)?; - - let call = OpaqueCall::from_tuple(&( - call_ids, - Address::from(AccountId::from(enclave_signer.public().0)), - ProxyType::Any, - 0u32, // delay - )); - - info!("add proxy call: 0x{}", hex::encode(call.0.clone())); - let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; - - ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false); - - // xt: delegate proxy authority to its own enclave accountid proxy.add_proxy() (panic if fails) - // caveat: must send from vault account. how to sign extrinsics with other keypair? - // sth like: extrinsics_factory.with_signer(keypair).create_extrinsics( - // write vault accountid to STF State (SgxExternalitiesType) with key ShardVaultAccountId to make it available also beyond service restart for non-primary SCV later - // return and log vault accountId - Ok(()) -} - /// Initialize the TOP pool author component. pub fn create_top_pool_author( connection_registry: Arc, diff --git a/enclave-runtime/src/lib.rs b/enclave-runtime/src/lib.rs index 6a90f57c3d..7bae31e38f 100644 --- a/enclave-runtime/src/lib.rs +++ b/enclave-runtime/src/lib.rs @@ -41,6 +41,7 @@ use crate::{ GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT, }, rpc::worker_api_direct::sidechain_io_handler, + shard_vault::init_proxied_shard_vault, utils::{ get_node_metadata_repository_from_integritee_solo_or_parachain, get_node_metadata_repository_from_target_a_solo_or_parachain, @@ -76,12 +77,12 @@ use std::{ string::{String, ToString}, vec::Vec, }; - mod attestation; mod empty_impls; mod initialization; mod ipfs; mod ocall; +mod shard_vault; mod utils; pub mod error; @@ -220,36 +221,6 @@ pub unsafe extern "C" fn get_ecc_signing_pubkey(pubkey: *mut u8, pubkey_size: u3 sgx_status_t::SGX_SUCCESS } -#[no_mangle] -pub unsafe extern "C" fn get_ecc_vault_pubkey( - shard: *const u8, - shard_size: u32, - pubkey: *mut u8, - pubkey_size: u32, -) -> sgx_status_t { - let shard = ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); - let state_handler = match GLOBAL_STATE_HANDLER_COMPONENT.get() { - Ok(s) => s, - Err(e) => { - error!("{:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - /*let vault_pubkey: Vec = state_handler - .execute_on_current(&shard, |state, _| state.state.get::>(&SHARD_VAULT_KEY.into())) - .unwrap() - .unwrap() - .to_vec(); - - let pubkey_slice = slice::from_raw_parts_mut(pubkey, pubkey_size as usize); - //debug!("Restored ECC pubkey: {:?}", signer_public); - - pubkey_slice.clone_from_slice(&vault_pubkey); - */ - sgx_status_t::SGX_ERROR_UNEXPECTED -} - #[no_mangle] pub unsafe extern "C" fn set_nonce( nonce: *const u32, @@ -460,22 +431,6 @@ pub unsafe extern "C" fn init_shard(shard: *const u8, shard_size: u32) -> sgx_st sgx_status_t::SGX_SUCCESS } -#[no_mangle] -pub unsafe extern "C" fn init_proxied_shard_vault( - shard: *const u8, - shard_size: u32, -) -> sgx_status_t { - let shard_identifier = - ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); - - if let Err(e) = initialization::init_proxied_shard_vault(shard_identifier) { - error!("Failed to initialize proxied shard vault ({:?}): {:?}", shard_identifier, 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/enclave-runtime/src/shard_vault.rs b/enclave-runtime/src/shard_vault.rs new file mode 100644 index 0000000000..e735de8550 --- /dev/null +++ b/enclave-runtime/src/shard_vault.rs @@ -0,0 +1,291 @@ +/* + Copyright 2021 Integritee 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. +*/ + +use crate::{ + error::{Error, Result as EnclaveResult}, + initialization::global_components::{ + EnclaveBlockImportConfirmationHandler, EnclaveGetterExecutor, EnclaveLightClientSeal, + EnclaveOCallApi, EnclaveRpcConnectionRegistry, EnclaveRpcResponder, + EnclaveShieldingKeyRepository, EnclaveSidechainApi, EnclaveSidechainBlockImportQueue, + EnclaveSidechainBlockImportQueueWorker, EnclaveSidechainBlockImporter, + EnclaveSidechainBlockSyncer, EnclaveStateFileIo, EnclaveStateHandler, + EnclaveStateInitializer, EnclaveStateObserver, EnclaveStateSnapshotRepository, + EnclaveStfEnclaveSigner, EnclaveTopPool, EnclaveTopPoolAuthor, + GLOBAL_ATTESTATION_HANDLER_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_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, + }, + ocall::OcallApi, + rpc::{rpc_response_channel::RpcResponseChannel, worker_api_direct::public_api_rpc_handler}, + utils::{ + get_extrinsic_factory_from_integritee_solo_or_parachain, + get_node_metadata_repository_from_integritee_solo_or_parachain, + get_triggered_dispatcher_from_solo_or_parachain, + get_validator_accessor_from_solo_or_parachain, + }, + Hash, +}; +use base58::ToBase58; +use codec::{Compact, Encode}; +use itc_direct_rpc_server::{ + create_determine_watch, rpc_connection_registry::ConnectionRegistry, + rpc_ws_handler::RpcWsHandler, +}; +use itc_tls_websocket_server::{ + certificate_generation::ed25519_self_signed_certificate, create_ws_server, ConnectionToken, + WebSocketServer, +}; +use itp_attestation_handler::IntelAttestationHandler; +use itp_component_container::{ComponentGetter, ComponentInitializer}; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_node_api::{ + api_client::{PairSignature, StaticExtrinsicSigner}, + metadata::{ + pallet_proxy::PROXY_DEPOSIT, + provider::{AccessNodeMetadata, Error as MetadataProviderError}, + }, +}; +use itp_nonce_cache::NonceCache; +use itp_ocall_api::EnclaveOnChainOCallApi; +use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE; +use itp_settings::files::{ + INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE, + TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, +}; +use itp_sgx_crypto::{ + get_aes_repository, get_ed25519_repository, get_rsa3072_repository, key_repository::AccessKey, +}; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_interface::SHARD_VAULT_KEY; +use itp_stf_state_handler::{ + file_io::StateDir, handle_state::HandleState, query_shard_state::QueryShardState, + state_snapshot_repository::VersionedStateAccess, + state_snapshot_repository_loader::StateSnapshotRepositoryLoader, StateHandler, +}; +use itp_top_pool::pool::Options as PoolOptions; +use itp_top_pool_author::author::AuthorTopFilter; +use itp_types::{ + parentchain::{AccountId, Address, Balance, ParentchainId, ProxyType}, + OpaqueCall, ShardIdentifier, +}; +use its_sidechain::block_composer::BlockComposer; +use log::*; +use sgx_types::sgx_status_t; +use sp_core::{ + blake2_256, + crypto::{DeriveJunction, Pair}, + ed25519, +}; +use std::{collections::HashMap, path::PathBuf, slice, string::String, sync::Arc, vec::Vec}; + +#[no_mangle] +pub unsafe extern "C" fn init_proxied_shard_vault( + shard: *const u8, + shard_size: u32, +) -> sgx_status_t { + let shard_identifier = + ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); + + if let Err(e) = init_proxied_shard_vault_internal(shard_identifier) { + error!("Failed to initialize proxied shard vault ({:?}): {:?}", shard_identifier, e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + + sgx_status_t::SGX_SUCCESS +} + +/// reads the shard vault account id form state if it has been initialized previously +#[no_mangle] +pub unsafe extern "C" fn get_ecc_vault_pubkey( + shard: *const u8, + shard_size: u32, + pubkey: *mut u8, + pubkey_size: u32, +) -> sgx_status_t { + let shard = ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); + + // todo + + //let pubkey_slice = slice::from_raw_parts_mut(pubkey, pubkey_size as usize); + //debug!("Restored ECC pubkey: {:?}", signer_public); + //pubkey_slice.clone_from_slice(&vault_pubkey); + sgx_status_t::SGX_ERROR_UNEXPECTED +} + +/// reads the shard vault account id form state if it has been initialized previously +pub(crate) fn get_shard_vault_account(shard: ShardIdentifier) -> EnclaveResult { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + + let vault_pubkey: Vec = state_handler + .execute_on_current(&shard, |state, _| { + let maybe_vault_key: Option<&Vec> = + state.state.get::>(&SHARD_VAULT_KEY.into()); + maybe_vault_key.unwrap().clone() + }) + .unwrap(); + + Err(Error::Other("unimplemented".into())) +} + +pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> EnclaveResult<()> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + if !state_handler.shard_exists(&shard).unwrap() { + return Err(Error::Other("shard not initialized".into())) + }; + + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let enclave_signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; + let enclave_extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + let vault = enclave_signer + .derive(vec![DeriveJunction::hard(shard.encode())].into_iter(), None) + .map_err(|e| Error::Other("failed to derive shard vault keypair".into()))? + .0; + + info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0.clone())); + + let (state_lock, mut state) = state_handler.load_for_mutation(&shard)?; + state.state.insert(SHARD_VAULT_KEY.into(), vault.public().0.to_vec()); + state_handler.write_after_mutation(state, state_lock, &shard)?; + // todo! + // parentchain-query: if shard vault not yet existing or self not proxy: + + // xt: send funds from enclave account to new vault account (panic if not enough funds) + + info!("send existential funds from enclave account to vault account"); + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.call_indexes("Balances", "transfer_keep_alive"))? + .map_err(MetadataProviderError::MetadataError)?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + Address::from(AccountId::from(vault.public().0)), + Compact(Balance::from(PROXY_DEPOSIT)), + )); + + info!("vault funding call: 0x{}", hex::encode(call.0.clone())); + let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; + + //this extrinsic must be included in a block before we can move on. otherwise the next will fail + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, true); + + // we are assuming nonce=0 here. + let nonce_cache = Arc::new(NonceCache::default()); + let vault_extrinsics_factory = enclave_extrinsics_factory + .with_signer(StaticExtrinsicSigner::<_, PairSignature>::new(vault), nonce_cache); + + info!("register enclave signer as proxy for shard vault"); + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.call_indexes("Proxy", "add_proxy"))? + .map_err(MetadataProviderError::MetadataError)?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + Address::from(AccountId::from(enclave_signer.public().0)), + ProxyType::Any, + 0u32, // delay + )); + + info!("add proxy call: 0x{}", hex::encode(call.0.clone())); + let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; + + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false); + + // xt: delegate proxy authority to its own enclave accountid proxy.add_proxy() (panic if fails) + // caveat: must send from vault account. how to sign extrinsics with other keypair? + // sth like: extrinsics_factory.with_signer(keypair).create_extrinsics( + // write vault accountid to STF State (SgxExternalitiesType) with key ShardVaultAccountId to make it available also beyond service restart for non-primary SCV later + // return and log vault accountId + Ok(()) +} + +pub(crate) fn add_shard_vault_proxy(shard: ShardIdentifier, proxy: AccountId) -> EnclaveResult<()> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + if !state_handler.shard_exists(&shard).unwrap() { + return Err(Error::Other("shard not initialized".into())) + }; + + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let enclave_signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; + let enclave_extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + let vault = enclave_signer + .derive(vec![DeriveJunction::hard(shard.encode())].into_iter(), None) + .map_err(|e| Error::Other("failed to derive shard vault keypair".into()))? + .0; + + info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0.clone())); + + let (state_lock, mut state) = state_handler.load_for_mutation(&shard)?; + state.state.insert(SHARD_VAULT_KEY.into(), vault.public().0.to_vec()); + state_handler.write_after_mutation(state, state_lock, &shard)?; + // todo! + // parentchain-query: if shard vault not yet existing or self not proxy: + + // xt: send funds from enclave account to new vault account (panic if not enough funds) + + info!("send existential funds from enclave account to vault account"); + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.call_indexes("Balances", "transfer_keep_alive"))? + .map_err(MetadataProviderError::MetadataError)?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + Address::from(AccountId::from(vault.public().0)), + Compact(Balance::from(PROXY_DEPOSIT)), + )); + + info!("vault funding call: 0x{}", hex::encode(call.0.clone())); + let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; + + //this extrinsic must be included in a block before we can move on. otherwise the next will fail + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, true); + + // we are assuming nonce=0 here. + let nonce_cache = Arc::new(NonceCache::default()); + let vault_extrinsics_factory = enclave_extrinsics_factory + .with_signer(StaticExtrinsicSigner::<_, PairSignature>::new(vault), nonce_cache); + + info!("register enclave signer as proxy for shard vault"); + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.call_indexes("Proxy", "add_proxy"))? + .map_err(MetadataProviderError::MetadataError)?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + Address::from(AccountId::from(enclave_signer.public().0)), + ProxyType::Any, + 0u32, // delay + )); + + info!("add proxy call: 0x{}", hex::encode(call.0.clone())); + let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; + + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false); + + // xt: delegate proxy authority to its own enclave accountid proxy.add_proxy() (panic if fails) + // caveat: must send from vault account. how to sign extrinsics with other keypair? + // sth like: extrinsics_factory.with_signer(keypair).create_extrinsics( + // write vault accountid to STF State (SgxExternalitiesType) with key ShardVaultAccountId to make it available also beyond service restart for non-primary SCV later + // return and log vault accountId + Ok(()) +} From ed26be783fcffbf567960062d243d68d93a92ffc Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Fri, 13 Oct 2023 12:56:55 +0200 Subject: [PATCH 16/26] secondary worker is registered as a vault proxy now --- enclave-runtime/src/initialization/mod.rs | 25 +-- enclave-runtime/src/lib.rs | 3 - enclave-runtime/src/shard_vault.rs | 171 ++++++-------------- enclave-runtime/src/tls_ra/tls_ra_server.rs | 28 ++-- 4 files changed, 65 insertions(+), 162 deletions(-) diff --git a/enclave-runtime/src/initialization/mod.rs b/enclave-runtime/src/initialization/mod.rs index a9b1e4a9c1..cb65c12cfd 100644 --- a/enclave-runtime/src/initialization/mod.rs +++ b/enclave-runtime/src/initialization/mod.rs @@ -49,7 +49,7 @@ use crate::{ Hash, }; use base58::ToBase58; -use codec::{Compact, Encode}; +use codec::Encode; use itc_direct_rpc_server::{ create_determine_watch, rpc_connection_registry::ConnectionRegistry, rpc_ws_handler::RpcWsHandler, @@ -60,16 +60,6 @@ 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::{ - api_client::{PairSignature, StaticExtrinsicSigner}, - metadata::{ - pallet_proxy::PROXY_DEPOSIT, - provider::{AccessNodeMetadata, Error as MetadataProviderError}, - }, -}; -use itp_nonce_cache::NonceCache; -use itp_ocall_api::EnclaveOnChainOCallApi; use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE; use itp_settings::files::{ INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE, @@ -78,8 +68,6 @@ 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_interface::SHARD_VAULT_KEY; use itp_stf_state_handler::{ file_io::StateDir, handle_state::HandleState, query_shard_state::QueryShardState, state_snapshot_repository::VersionedStateAccess, @@ -87,17 +75,10 @@ use itp_stf_state_handler::{ }; use itp_top_pool::pool::Options as PoolOptions; use itp_top_pool_author::author::AuthorTopFilter; -use itp_types::{ - parentchain::{AccountId, Address, Balance, ParentchainId, ProxyType}, - OpaqueCall, ShardIdentifier, -}; +use itp_types::{parentchain::ParentchainId, ShardIdentifier}; use its_sidechain::block_composer::BlockComposer; use log::*; -use sp_core::{ - blake2_256, - crypto::{DeriveJunction, Pair}, - ed25519, -}; +use sp_core::crypto::Pair; use std::{collections::HashMap, path::PathBuf, string::String, sync::Arc}; pub(crate) fn init_enclave( mu_ra_url: String, diff --git a/enclave-runtime/src/lib.rs b/enclave-runtime/src/lib.rs index 7bae31e38f..7c375b8205 100644 --- a/enclave-runtime/src/lib.rs +++ b/enclave-runtime/src/lib.rs @@ -41,7 +41,6 @@ use crate::{ GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT, }, rpc::worker_api_direct::sidechain_io_handler, - shard_vault::init_proxied_shard_vault, utils::{ get_node_metadata_repository_from_integritee_solo_or_parachain, get_node_metadata_repository_from_target_a_solo_or_parachain, @@ -61,8 +60,6 @@ use itp_node_api::metadata::NodeMetadata; use itp_nonce_cache::{MutateNonce, Nonce}; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; use itp_sgx_crypto::key_repository::AccessPubkey; -use itp_stf_interface::SHARD_VAULT_KEY; -use itp_stf_state_handler::handle_state::HandleState; use itp_storage::{StorageProof, StorageProofChecker}; use itp_types::{ShardIdentifier, SignedBlock}; use itp_utils::write_slice_and_whitespace_pad; diff --git a/enclave-runtime/src/shard_vault.rs b/enclave-runtime/src/shard_vault.rs index e735de8550..d4498a97cc 100644 --- a/enclave-runtime/src/shard_vault.rs +++ b/enclave-runtime/src/shard_vault.rs @@ -17,45 +17,16 @@ use crate::{ error::{Error, Result as EnclaveResult}, initialization::global_components::{ - EnclaveBlockImportConfirmationHandler, EnclaveGetterExecutor, EnclaveLightClientSeal, - EnclaveOCallApi, EnclaveRpcConnectionRegistry, EnclaveRpcResponder, - EnclaveShieldingKeyRepository, EnclaveSidechainApi, EnclaveSidechainBlockImportQueue, - EnclaveSidechainBlockImportQueueWorker, EnclaveSidechainBlockImporter, - EnclaveSidechainBlockSyncer, EnclaveStateFileIo, EnclaveStateHandler, - EnclaveStateInitializer, EnclaveStateObserver, EnclaveStateSnapshotRepository, - EnclaveStfEnclaveSigner, EnclaveTopPool, EnclaveTopPoolAuthor, - GLOBAL_ATTESTATION_HANDLER_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_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, + GLOBAL_OCALL_API_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, }, - ocall::OcallApi, - rpc::{rpc_response_channel::RpcResponseChannel, worker_api_direct::public_api_rpc_handler}, utils::{ get_extrinsic_factory_from_integritee_solo_or_parachain, get_node_metadata_repository_from_integritee_solo_or_parachain, - get_triggered_dispatcher_from_solo_or_parachain, - get_validator_accessor_from_solo_or_parachain, }, - Hash, }; -use base58::ToBase58; -use codec::{Compact, Encode}; -use itc_direct_rpc_server::{ - create_determine_watch, rpc_connection_registry::ConnectionRegistry, - rpc_ws_handler::RpcWsHandler, -}; -use itc_tls_websocket_server::{ - certificate_generation::ed25519_self_signed_certificate, create_ws_server, ConnectionToken, - WebSocketServer, -}; -use itp_attestation_handler::IntelAttestationHandler; -use itp_component_container::{ComponentGetter, ComponentInitializer}; +use codec::{Compact, Decode, Encode}; +use itp_component_container::ComponentGetter; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::{ api_client::{PairSignature, StaticExtrinsicSigner}, @@ -64,38 +35,20 @@ use itp_node_api::{ provider::{AccessNodeMetadata, Error as MetadataProviderError}, }, }; +use itp_node_api_metadata::pallet_proxy::ProxyCallIndexes; use itp_nonce_cache::NonceCache; use itp_ocall_api::EnclaveOnChainOCallApi; -use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE; -use itp_settings::files::{ - INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE, - TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, -}; -use itp_sgx_crypto::{ - get_aes_repository, get_ed25519_repository, get_rsa3072_repository, key_repository::AccessKey, -}; -use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_sgx_crypto::key_repository::AccessKey; use itp_stf_interface::SHARD_VAULT_KEY; -use itp_stf_state_handler::{ - file_io::StateDir, handle_state::HandleState, query_shard_state::QueryShardState, - state_snapshot_repository::VersionedStateAccess, - state_snapshot_repository_loader::StateSnapshotRepositoryLoader, StateHandler, -}; -use itp_top_pool::pool::Options as PoolOptions; -use itp_top_pool_author::author::AuthorTopFilter; +use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; use itp_types::{ parentchain::{AccountId, Address, Balance, ParentchainId, ProxyType}, OpaqueCall, ShardIdentifier, }; -use its_sidechain::block_composer::BlockComposer; use log::*; use sgx_types::sgx_status_t; -use sp_core::{ - blake2_256, - crypto::{DeriveJunction, Pair}, - ed25519, -}; -use std::{collections::HashMap, path::PathBuf, slice, string::String, sync::Arc, vec::Vec}; +use sp_core::crypto::{DeriveJunction, Pair}; +use std::{slice, sync::Arc, vec::Vec}; #[no_mangle] pub unsafe extern "C" fn init_proxied_shard_vault( @@ -123,11 +76,16 @@ pub unsafe extern "C" fn get_ecc_vault_pubkey( ) -> sgx_status_t { let shard = ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); - // todo + let shard_vault = match get_shard_vault_account(shard) { + Ok(account) => account, + Err(e) => { + error!("Failed to fetch shard vault account: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; - //let pubkey_slice = slice::from_raw_parts_mut(pubkey, pubkey_size as usize); - //debug!("Restored ECC pubkey: {:?}", signer_public); - //pubkey_slice.clone_from_slice(&vault_pubkey); + let pubkey_slice = slice::from_raw_parts_mut(pubkey, pubkey_size as usize); + pubkey_slice.clone_from_slice(&shard_vault.encode().as_slice()); sgx_status_t::SGX_ERROR_UNEXPECTED } @@ -135,15 +93,15 @@ pub unsafe extern "C" fn get_ecc_vault_pubkey( pub(crate) fn get_shard_vault_account(shard: ShardIdentifier) -> EnclaveResult { let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; - let vault_pubkey: Vec = state_handler + state_handler .execute_on_current(&shard, |state, _| { - let maybe_vault_key: Option<&Vec> = - state.state.get::>(&SHARD_VAULT_KEY.into()); - maybe_vault_key.unwrap().clone() - }) - .unwrap(); - - Err(Error::Other("unimplemented".into())) + state + .state + .get::>(&SHARD_VAULT_KEY.into()) + .map(|v| Decode::decode(&mut v.clone().as_slice()).ok()) + .flatten() + })? + .ok_or(Error::Other("failed to fetch shard vault account. has it been initialized?".into())) } pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> EnclaveResult<()> { @@ -158,7 +116,7 @@ pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> Encla let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; let vault = enclave_signer .derive(vec![DeriveJunction::hard(shard.encode())].into_iter(), None) - .map_err(|e| Error::Other("failed to derive shard vault keypair".into()))? + .map_err(|_| Error::Other("failed to derive shard vault keypair".into()))? .0; info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0.clone())); @@ -186,7 +144,7 @@ pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> Encla let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; //this extrinsic must be included in a block before we can move on. otherwise the next will fail - ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, true); + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, true)?; // we are assuming nonce=0 here. let nonce_cache = Arc::new(NonceCache::default()); @@ -208,7 +166,7 @@ pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> Encla info!("add proxy call: 0x{}", hex::encode(call.0.clone())); let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; - ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false); + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false)?; // xt: delegate proxy authority to its own enclave accountid proxy.add_proxy() (panic if fails) // caveat: must send from vault account. how to sign extrinsics with other keypair? @@ -225,67 +183,32 @@ pub(crate) fn add_shard_vault_proxy(shard: ShardIdentifier, proxy: AccountId) -> }; let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; - let enclave_signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; let enclave_extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; - let vault = enclave_signer - .derive(vec![DeriveJunction::hard(shard.encode())].into_iter(), None) - .map_err(|e| Error::Other("failed to derive shard vault keypair".into()))? - .0; + let vault = get_shard_vault_account(shard)?; - info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0.clone())); + debug!( + "adding proxy 0x{} to shard vault account 0x{}", + hex::encode(proxy.clone()), + hex::encode(vault.clone()) + ); - let (state_lock, mut state) = state_handler.load_for_mutation(&shard)?; - state.state.insert(SHARD_VAULT_KEY.into(), vault.public().0.to_vec()); - state_handler.write_after_mutation(state, state_lock, &shard)?; - // todo! - // parentchain-query: if shard vault not yet existing or self not proxy: - - // xt: send funds from enclave account to new vault account (panic if not enough funds) - - info!("send existential funds from enclave account to vault account"); - let call_ids = node_metadata_repo - .get_from_metadata(|m| m.call_indexes("Balances", "transfer_keep_alive"))? - .map_err(MetadataProviderError::MetadataError)?; - - let call = OpaqueCall::from_tuple(&( - call_ids, - Address::from(AccountId::from(vault.public().0)), - Compact(Balance::from(PROXY_DEPOSIT)), - )); - - info!("vault funding call: 0x{}", hex::encode(call.0.clone())); - let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; - - //this extrinsic must be included in a block before we can move on. otherwise the next will fail - ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, true); - - // we are assuming nonce=0 here. - let nonce_cache = Arc::new(NonceCache::default()); - let vault_extrinsics_factory = enclave_extrinsics_factory - .with_signer(StaticExtrinsicSigner::<_, PairSignature>::new(vault), nonce_cache); - - info!("register enclave signer as proxy for shard vault"); - let call_ids = node_metadata_repo - .get_from_metadata(|m| m.call_indexes("Proxy", "add_proxy"))? - .map_err(MetadataProviderError::MetadataError)?; - - let call = OpaqueCall::from_tuple(&( - call_ids, - Address::from(AccountId::from(enclave_signer.public().0)), + let add_proxy_call = OpaqueCall::from_tuple(&( + node_metadata_repo.get_from_metadata(|m| m.add_proxy_call_indexes())??, + Address::from(proxy), ProxyType::Any, 0u32, // delay )); + let call = OpaqueCall::from_tuple(&( + node_metadata_repo.get_from_metadata(|m| m.proxy_call_indexes())??, + Address::from(vault), + None::, + add_proxy_call, + )); - info!("add proxy call: 0x{}", hex::encode(call.0.clone())); - let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; - - ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false); + info!("proxied add proxy call: 0x{}", hex::encode(call.0.clone())); + let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; - // xt: delegate proxy authority to its own enclave accountid proxy.add_proxy() (panic if fails) - // caveat: must send from vault account. how to sign extrinsics with other keypair? - // sth like: extrinsics_factory.with_signer(keypair).create_extrinsics( - // write vault accountid to STF State (SgxExternalitiesType) with key ShardVaultAccountId to make it available also beyond service restart for non-primary SCV later - // return and log vault accountId + ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false)?; Ok(()) } diff --git a/enclave-runtime/src/tls_ra/tls_ra_server.rs b/enclave-runtime/src/tls_ra/tls_ra_server.rs index 6e5c03ed58..7d6b088e46 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_server.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -26,17 +26,18 @@ use crate::{ GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, }, ocall::OcallApi, + shard_vault::add_shard_vault_proxy, tls_ra::seal_handler::UnsealStateAndKeys, GLOBAL_STATE_HANDLER_COMPONENT, }; use codec::Decode; -use itp_attestation_handler::{cert::parse_cert_issuer, RemoteAttestationType}; +use itp_attestation_handler::RemoteAttestationType; use itp_component_container::ComponentGetter; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; -use itp_types::{AccountId, ShardIdentifier}; +use itp_types::ShardIdentifier; use log::*; -use rustls::{ServerConfig, ServerSession, Session, StreamOwned}; +use rustls::{ServerConfig, ServerSession, StreamOwned}; use sgx_types::*; use std::{ backtrace::{self, PrintFormat}, @@ -83,7 +84,7 @@ where } /// Sends all relevant data of the specific shard to the client. - fn handle_shard_request_from_client(&mut self) -> EnclaveResult { + fn handle_shard_request_from_client(&mut self) -> EnclaveResult<()> { println!( " [Enclave] (MU-RA-Server) handle_shard_request_from_client, calling read_shard()" ); @@ -91,13 +92,19 @@ where println!(" [Enclave] (MU-RA-Server) handle_shard_request_from_client, await_shard_request_from_client() OK"); println!(" [Enclave] (MU-RA-Server) handle_shard_request_from_client, write_all()"); self.write_provisioning_payloads(&request.shard)?; - Ok(request.account) + + info!( + "will make client account 0x{} a proxy of vault for shard {:?}", + hex::encode(request.account.clone()), + request.shard + ); + add_shard_vault_proxy(request.shard, request.account)?; + + Ok(()) } /// Read the shard of the state the client wants to receive. fn await_shard_request_from_client(&mut self) -> EnclaveResult { - let mut shard_holder = ShardIdentifier::default(); - let shard = shard_holder.as_fixed_bytes_mut(); let mut request = [0u8; std::mem::size_of::()]; println!( " [Enclave] (MU-RA-Server) await_shard_request_from_client, calling read_exact()" @@ -270,12 +277,7 @@ pub(crate) fn run_state_provisioning_server_internal< println!( " [Enclave] (MU-RA-Server) MU-RA successful, calling handle_shard_request_from_client()" ); - let client_account = server.handle_shard_request_from_client()?; - - info!("will make client account 0x{} a proxy of vault", hex::encode(client_account.clone())); - // todo! add client account as a proxy to shard vault account - - Ok(()) + server.handle_shard_request_from_client() } fn tls_server_session_stream( From b72c063562249a712ccb1baeb96b7e6949b2b4f8 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Fri, 13 Oct 2023 14:11:44 +0200 Subject: [PATCH 17/26] cleanup --- app-libs/stf/src/trusted_call.rs | 4 ++- .../enclave-api/src/enclave_base.rs | 22 +++++++++++----- enclave-runtime/src/shard_vault.rs | 17 ++++++------ enclave-runtime/src/tls_ra/authentication.rs | 4 +-- enclave-runtime/src/tls_ra/tls_ra_client.rs | 2 ++ enclave-runtime/src/utils.rs | 26 ------------------- service/src/main.rs | 22 ++++++++++++---- .../src/ocall_bridge/worker_on_chain_ocall.rs | 3 +-- 8 files changed, 49 insertions(+), 51 deletions(-) diff --git a/app-libs/stf/src/trusted_call.rs b/app-libs/stf/src/trusted_call.rs index 7625e53e1a..4f595ab3fe 100644 --- a/app-libs/stf/src/trusted_call.rs +++ b/app-libs/stf/src/trusted_call.rs @@ -257,7 +257,9 @@ where // the extrinsic will be sent and potentially deplete the vault at the current state which // is nothing to worry about before we solve mentioned issue. let vault_pubkey: [u8; 32] = get_storage_by_key_hash(SHARD_VAULT_KEY.into()) - .ok_or(StfError::Dispatch("shard vault key hasn't been set".to_string()))?; + .ok_or_else(|| { + StfError::Dispatch("shard vault key hasn't been set".to_string()) + })?; let vault_address = Address::from(AccountId::from(vault_pubkey)); let vault_transfer_call = OpaqueCall::from_tuple(&( node_metadata_repo diff --git a/core-primitives/enclave-api/src/enclave_base.rs b/core-primitives/enclave-api/src/enclave_base.rs index 6b317d8b9f..bfdd285518 100644 --- a/core-primitives/enclave-api/src/enclave_base.rs +++ b/core-primitives/enclave-api/src/enclave_base.rs @@ -25,6 +25,7 @@ use itp_enclave_api_ffi as ffi; use itp_settings::worker::{ HEADER_MAX_SIZE, MR_ENCLAVE_SIZE, SHIELDING_KEY_SIZE, SIGNING_KEY_SIZE, }; +use itp_types::ShardIdentifier; use log::*; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sgx_types::*; @@ -57,7 +58,7 @@ pub trait EnclaveBase: Send + Sync + 'static { fn init_shard(&self, shard: Vec) -> EnclaveResult<()>; /// Initialize a new shard. - fn init_proxied_shard_vault(&self, shard: Vec) -> EnclaveResult<()>; + fn init_proxied_shard_vault(&self, shard: &ShardIdentifier) -> EnclaveResult<()>; /// Trigger the import of parentchain block explicitly. Used when initializing a light-client /// with a triggered import dispatcher. @@ -76,7 +77,7 @@ pub trait EnclaveBase: Send + Sync + 'static { fn get_ecc_signing_pubkey(&self) -> EnclaveResult; - fn get_ecc_vault_pubkey(&self, shard: Vec) -> EnclaveResult; + fn get_ecc_vault_pubkey(&self, shard: &ShardIdentifier) -> EnclaveResult; fn get_fingerprint(&self) -> EnclaveResult; } @@ -169,11 +170,17 @@ impl EnclaveBase for Enclave { Ok(()) } - fn init_proxied_shard_vault(&self, shard: Vec) -> EnclaveResult<()> { + fn init_proxied_shard_vault(&self, shard: &ShardIdentifier) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; + let shard_bytes = shard.encode(); let result = unsafe { - ffi::init_proxied_shard_vault(self.eid, &mut retval, shard.as_ptr(), shard.len() as u32) + ffi::init_proxied_shard_vault( + self.eid, + &mut retval, + shard_bytes.as_ptr(), + shard_bytes.len() as u32, + ) }; ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); @@ -293,16 +300,17 @@ impl EnclaveBase for Enclave { Ok(ed25519::Public::from_raw(pubkey)) } - fn get_ecc_vault_pubkey(&self, shard: Vec) -> EnclaveResult { + fn get_ecc_vault_pubkey(&self, shard: &ShardIdentifier) -> EnclaveResult { let mut retval = sgx_status_t::SGX_SUCCESS; let mut pubkey = [0u8; SIGNING_KEY_SIZE]; + let shard_bytes = shard.encode(); let result = unsafe { ffi::get_ecc_vault_pubkey( self.eid, &mut retval, - shard.as_ptr(), - shard.len() as u32, + shard_bytes.as_ptr(), + shard_bytes.len() as u32, pubkey.as_mut_ptr(), pubkey.len() as u32, ) diff --git a/enclave-runtime/src/shard_vault.rs b/enclave-runtime/src/shard_vault.rs index d4498a97cc..a1c59e530d 100644 --- a/enclave-runtime/src/shard_vault.rs +++ b/enclave-runtime/src/shard_vault.rs @@ -42,7 +42,7 @@ use itp_sgx_crypto::key_repository::AccessKey; use itp_stf_interface::SHARD_VAULT_KEY; use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; use itp_types::{ - parentchain::{AccountId, Address, Balance, ParentchainId, ProxyType}, + parentchain::{AccountId, Address, ParentchainId, ProxyType}, OpaqueCall, ShardIdentifier, }; use log::*; @@ -85,8 +85,8 @@ pub unsafe extern "C" fn get_ecc_vault_pubkey( }; let pubkey_slice = slice::from_raw_parts_mut(pubkey, pubkey_size as usize); - pubkey_slice.clone_from_slice(&shard_vault.encode().as_slice()); - sgx_status_t::SGX_ERROR_UNEXPECTED + pubkey_slice.clone_from_slice(shard_vault.encode().as_slice()); + sgx_status_t::SGX_SUCCESS } /// reads the shard vault account id form state if it has been initialized previously @@ -98,10 +98,11 @@ pub(crate) fn get_shard_vault_account(shard: ShardIdentifier) -> EnclaveResult>(&SHARD_VAULT_KEY.into()) - .map(|v| Decode::decode(&mut v.clone().as_slice()).ok()) - .flatten() + .and_then(|v| Decode::decode(&mut v.clone().as_slice()).ok()) })? - .ok_or(Error::Other("failed to fetch shard vault account. has it been initialized?".into())) + .ok_or_else(|| { + Error::Other("failed to fetch shard vault account. has it been initialized?".into()) + }) } pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> EnclaveResult<()> { @@ -119,7 +120,7 @@ pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> Encla .map_err(|_| Error::Other("failed to derive shard vault keypair".into()))? .0; - info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0.clone())); + info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0)); let (state_lock, mut state) = state_handler.load_for_mutation(&shard)?; state.state.insert(SHARD_VAULT_KEY.into(), vault.public().0.to_vec()); @@ -137,7 +138,7 @@ pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> Encla let call = OpaqueCall::from_tuple(&( call_ids, Address::from(AccountId::from(vault.public().0)), - Compact(Balance::from(PROXY_DEPOSIT)), + Compact(PROXY_DEPOSIT), )); info!("vault funding call: 0x{}", hex::encode(call.0.clone())); diff --git a/enclave-runtime/src/tls_ra/authentication.rs b/enclave-runtime/src/tls_ra/authentication.rs index ab84a76e71..c2dbdd3e92 100644 --- a/enclave-runtime/src/tls_ra/authentication.rs +++ b/enclave-runtime/src/tls_ra/authentication.rs @@ -52,7 +52,7 @@ where ) -> Result { debug!("client cert: {:?}", certs); let issuer = cert::parse_cert_issuer(&certs[0].0).unwrap(); - info!("client signer (issuer) is: 0x{}", hex::encode(issuer.clone())); + info!("client signer (issuer) is: 0x{}", hex::encode(issuer)); // This call will automatically verify cert is properly signed if self.skip_ra { @@ -107,7 +107,7 @@ where ) -> Result { debug!("server cert: {:?}", certs); let issuer = cert::parse_cert_issuer(&certs[0].0).unwrap(); - info!("server signer (issuer) is: 0x{}", hex::encode(issuer.clone())); + info!("server signer (issuer) is: 0x{}", hex::encode(issuer)); if self.skip_ra { warn!("Skip verifying ra-report"); diff --git a/enclave-runtime/src/tls_ra/tls_ra_client.rs b/enclave-runtime/src/tls_ra/tls_ra_client.rs index 0fac6f3890..428961da77 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_client.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_client.rs @@ -243,6 +243,8 @@ pub unsafe extern "C" fn request_state_provisioning( } /// Internal [`request_state_provisioning`] function to be able to use the handy `?` operator. +// allowing clippy rant because this fn will be refactored with MU RA deprecation +#[allow(clippy::too_many_arguments)] pub(crate) fn request_state_provisioning_internal( socket_fd: c_int, sign_type: sgx_quote_sign_type_t, diff --git a/enclave-runtime/src/utils.rs b/enclave-runtime/src/utils.rs index 7249e53dab..4c58da0d01 100644 --- a/enclave-runtime/src/utils.rs +++ b/enclave-runtime/src/utils.rs @@ -160,32 +160,6 @@ pub(crate) fn get_extrinsic_factory_from_integritee_solo_or_parachain( Ok(extrinsics_factory) } -pub(crate) fn get_extrinsic_factory_from_target_a_solo_or_parachain( -) -> Result> { - let extrinsics_factory = - if let Ok(solochain_handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { - solochain_handler.extrinsics_factory.clone() - } else if let Ok(parachain_handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { - parachain_handler.extrinsics_factory.clone() - } else { - return Err(Error::NoTargetAParentchainAssigned) - }; - Ok(extrinsics_factory) -} - -pub(crate) fn get_extrinsic_factory_from_target_b_solo_or_parachain( -) -> Result> { - let extrinsics_factory = - if let Ok(solochain_handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { - solochain_handler.extrinsics_factory.clone() - } else if let Ok(parachain_handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { - parachain_handler.extrinsics_factory.clone() - } else { - return Err(Error::NoTargetBParentchainAssigned) - }; - Ok(extrinsics_factory) -} - pub(crate) fn get_stf_executor_from_solo_or_parachain() -> Result> { let stf_executor = if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { diff --git a/service/src/main.rs b/service/src/main.rs index 49d429e98d..2ed357f6af 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -594,8 +594,23 @@ fn start_worker( }) .unwrap(); - println!("initializing proxied shard vault account now"); - enclave.init_proxied_shard_vault(shard.encode()); + if let Ok(shard_vault) = enclave.get_ecc_vault_pubkey(shard) { + println!( + "shard vault account is already initialized in state: {}", + shard_vault.to_ss58check() + ); + } else { + if we_are_primary_validateer { + println!("initializing proxied shard vault account now"); + enclave.init_proxied_shard_vault(shard).unwrap(); + println!( + "initialized shard vault account: : {}", + enclave.get_ecc_vault_pubkey(shard).unwrap().to_ss58check() + ); + } else { + panic!("no vault account has been initialized and we are not the primary worker"); + } + } } // ------------------------------------------------------------------------ @@ -608,7 +623,6 @@ fn start_worker( &enclave, &tee_accountid, url, - shard, ParentchainId::TargetA, is_development_mode, ) @@ -619,7 +633,6 @@ fn start_worker( &enclave, &tee_accountid, url, - shard, ParentchainId::TargetB, is_development_mode, ) @@ -641,7 +654,6 @@ fn init_target_parentchain( enclave: &Arc, tee_account_id: &AccountId32, url: String, - shard: &ShardIdentifier, parentchain_id: ParentchainId, is_development_mode: bool, ) where diff --git a/service/src/ocall_bridge/worker_on_chain_ocall.rs b/service/src/ocall_bridge/worker_on_chain_ocall.rs index c1481288ee..5908435023 100644 --- a/service/src/ocall_bridge/worker_on_chain_ocall.rs +++ b/service/src/ocall_bridge/worker_on_chain_ocall.rs @@ -25,8 +25,7 @@ use log::*; use sp_runtime::OpaqueExtrinsic; use std::{sync::Arc, vec::Vec}; use substrate_api_client::{ - ac_primitives::serde_impls::StorageKey, rpc_api::SubmitAndWatchUntilSuccess, GetStorage, - SubmitAndWatch, SubmitExtrinsic, XtStatus, + ac_primitives::serde_impls::StorageKey, GetStorage, SubmitAndWatch, SubmitExtrinsic, XtStatus, }; pub struct WorkerOnChainOCall { From 4d2c0000f3d85f1e4db2e54d872dd582ecacab12 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Fri, 13 Oct 2023 14:17:51 +0200 Subject: [PATCH 18/26] clippy --- service/src/main.rs | 18 ++++++++---------- .../src/ocall_bridge/worker_on_chain_ocall.rs | 14 ++++++-------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/service/src/main.rs b/service/src/main.rs index 2ed357f6af..5dbe9c1333 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -599,17 +599,15 @@ fn start_worker( "shard vault account is already initialized in state: {}", shard_vault.to_ss58check() ); + } else if we_are_primary_validateer { + println!("initializing proxied shard vault account now"); + enclave.init_proxied_shard_vault(shard).unwrap(); + println!( + "initialized shard vault account: : {}", + enclave.get_ecc_vault_pubkey(shard).unwrap().to_ss58check() + ); } else { - if we_are_primary_validateer { - println!("initializing proxied shard vault account now"); - enclave.init_proxied_shard_vault(shard).unwrap(); - println!( - "initialized shard vault account: : {}", - enclave.get_ecc_vault_pubkey(shard).unwrap().to_ss58check() - ); - } else { - panic!("no vault account has been initialized and we are not the primary worker"); - } + panic!("no vault account has been initialized and we are not the primary worker"); } } diff --git a/service/src/ocall_bridge/worker_on_chain_ocall.rs b/service/src/ocall_bridge/worker_on_chain_ocall.rs index 5908435023..f322c6337f 100644 --- a/service/src/ocall_bridge/worker_on_chain_ocall.rs +++ b/service/src/ocall_bridge/worker_on_chain_ocall.rs @@ -145,14 +145,12 @@ where e ); } - } else { - if let Err(e) = api.submit_opaque_extrinsic(&call.encode().into()) { - error!( - "Could not send extrinsic to node: {:?}, error: {:?}", - serde_json::to_string(&call), - e - ); - } + } else if let Err(e) = api.submit_opaque_extrinsic(&call.encode().into()) { + error!( + "Could not send extrinsic to node: {:?}, error: {:?}", + serde_json::to_string(&call), + e + ); } } } From 9bc2e60a741e736b459171794100889a6b2a1d03 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Fri, 13 Oct 2023 14:56:07 +0200 Subject: [PATCH 19/26] doc cleanup --- .../enclave-api/src/enclave_base.rs | 3 +- enclave-runtime/src/shard_vault.rs | 10 ------ enclave-runtime/src/tls_ra/README.md | 32 +++++++++++-------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/core-primitives/enclave-api/src/enclave_base.rs b/core-primitives/enclave-api/src/enclave_base.rs index bfdd285518..6ef543656c 100644 --- a/core-primitives/enclave-api/src/enclave_base.rs +++ b/core-primitives/enclave-api/src/enclave_base.rs @@ -57,7 +57,7 @@ pub trait EnclaveBase: Send + Sync + 'static { /// Initialize a new shard. fn init_shard(&self, shard: Vec) -> EnclaveResult<()>; - /// Initialize a new shard. + /// Initialize a new shard vault account and register enclave signer as its proxy. fn init_proxied_shard_vault(&self, shard: &ShardIdentifier) -> EnclaveResult<()>; /// Trigger the import of parentchain block explicitly. Used when initializing a light-client @@ -77,6 +77,7 @@ pub trait EnclaveBase: Send + Sync + 'static { fn get_ecc_signing_pubkey(&self) -> EnclaveResult; + /// retrieve vault account from shard state fn get_ecc_vault_pubkey(&self, shard: &ShardIdentifier) -> EnclaveResult; fn get_fingerprint(&self) -> EnclaveResult; diff --git a/enclave-runtime/src/shard_vault.rs b/enclave-runtime/src/shard_vault.rs index a1c59e530d..5045620eaa 100644 --- a/enclave-runtime/src/shard_vault.rs +++ b/enclave-runtime/src/shard_vault.rs @@ -125,10 +125,6 @@ pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> Encla let (state_lock, mut state) = state_handler.load_for_mutation(&shard)?; state.state.insert(SHARD_VAULT_KEY.into(), vault.public().0.to_vec()); state_handler.write_after_mutation(state, state_lock, &shard)?; - // todo! - // parentchain-query: if shard vault not yet existing or self not proxy: - - // xt: send funds from enclave account to new vault account (panic if not enough funds) info!("send existential funds from enclave account to vault account"); let call_ids = node_metadata_repo @@ -168,12 +164,6 @@ pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> Encla let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false)?; - - // xt: delegate proxy authority to its own enclave accountid proxy.add_proxy() (panic if fails) - // caveat: must send from vault account. how to sign extrinsics with other keypair? - // sth like: extrinsics_factory.with_signer(keypair).create_extrinsics( - // write vault accountid to STF State (SgxExternalitiesType) with key ShardVaultAccountId to make it available also beyond service restart for non-primary SCV later - // return and log vault accountId Ok(()) } diff --git a/enclave-runtime/src/tls_ra/README.md b/enclave-runtime/src/tls_ra/README.md index 9c2655f04d..b7f8b1aebb 100644 --- a/enclave-runtime/src/tls_ra/README.md +++ b/enclave-runtime/src/tls_ra/README.md @@ -6,17 +6,23 @@ Light client storage can also be provisioned to avoid re-synching the entire par ```mermaid sequenceDiagram -participant server -participant client -server ->> server: generate shielding & state encryption key -server ->> server: init_shard & sync parentchains -client ->> server: enclave_request_state_provisioning -activate client -client ->> client: qe_get_target_info - - - -deactivate client - - +participant untrusted_server +participant enclave_server +participant enclave_client +participant untrusted_client +enclave_server ->> enclave_server: generate shielding & state encryption key +enclave_server ->> enclave_server: init_shard & sync parentchains +untrusted_client ->> untrusted_server: connect TCP +untrusted_client ->> enclave_client: request_state_provisioning +activate enclave_client +untrusted_server ->> enclave_server: run_state_provisioning_server +activate enclave_server +enclave_client ->> enclave_server: open TLS session (including MU RA) +enclave_client ->> enclave_server: request_state_provisioning(shard, account) +enclave_server ->> enclave_client: write_provisioning_payloads +enclave_server ->> enclave_server: add client as vault proxy for shard + +deactivate enclave_client +deactivate enclave_server +untrusted_client --> untrusted_server: disconnect TCP ``` From 757c07a04634c6f0af6a011b56144e056cf8e545 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Fri, 13 Oct 2023 15:03:52 +0200 Subject: [PATCH 20/26] doc pimp --- enclave-runtime/src/tls_ra/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/enclave-runtime/src/tls_ra/README.md b/enclave-runtime/src/tls_ra/README.md index b7f8b1aebb..3f4effa148 100644 --- a/enclave-runtime/src/tls_ra/README.md +++ b/enclave-runtime/src/tls_ra/README.md @@ -4,6 +4,8 @@ each worker runs a provisioning server for other workers of the same MRENCLAVE a Light client storage can also be provisioned to avoid re-synching the entire parentchains with each worker +enclave instances are short-lived on both sides, just for a single request. + ```mermaid sequenceDiagram participant untrusted_server @@ -17,12 +19,15 @@ untrusted_client ->> enclave_client: request_state_provisioning activate enclave_client untrusted_server ->> enclave_server: run_state_provisioning_server activate enclave_server +enclave_server ->> enclave_server: load state and secrets enclave_client ->> enclave_server: open TLS session (including MU RA) enclave_client ->> enclave_server: request_state_provisioning(shard, account) enclave_server ->> enclave_client: write_provisioning_payloads enclave_server ->> enclave_server: add client as vault proxy for shard - +enclave_client ->> enclave_client: seal state and secrets to disk +enclave_client -->> untrusted_client: _ deactivate enclave_client +enclave_server -->> untrusted_server: _ deactivate enclave_server untrusted_client --> untrusted_server: disconnect TCP ``` From 2b7ed16c9b4ce10077c12782d174b20a4705c8df Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Fri, 13 Oct 2023 15:09:05 +0200 Subject: [PATCH 21/26] cleanup --- service/src/main.rs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/service/src/main.rs b/service/src/main.rs index 5dbe9c1333..e88f1d1176 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -681,17 +681,6 @@ fn init_target_parentchain( let last_synched_header = parentchain_handler.sync_parentchain(last_synched_header).unwrap(); - //setup_proxied_shard_vault - //println!("initializing proxied shard vault account now"); - // todo: generic for targetA/B - //enclave.init_proxied_shard_vault(shard.encode()); - - // if we are primary validateer and if doesn't exist, create a pure_proxy for shard vault - // todo - - // check if exists - //tee_account_id - // start parentchain syncing loop (subscribe to header updates) thread::Builder::new() .name(format!("{:?}_parentchain_sync_loop", parentchain_id)) @@ -762,12 +751,6 @@ where panic!("[{:?}] Could not set the node metadata in the enclave", parentchain_id) }); - // todo!: ensure shard vault proxy exists - // should only be registered by primary worker for shard - // check if metadata contains proxy pallet and issue warning otherwise - // check if shard vault exists (must derive accountid from primary worker and index - // let enclave compose proxy.create_pure(proxyType: Any, delay:0, index:0) - (parentchain_handler, last_synced_header) } From bb69ebda915123070502d4ae9225116d7cc5642e Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Tue, 24 Oct 2023 11:44:43 +0200 Subject: [PATCH 22/26] reverting polling fix which is solved in another PR --- service/src/parentchain_handler.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/service/src/parentchain_handler.rs b/service/src/parentchain_handler.rs index 9ffae8c5b6..8b11e92b87 100644 --- a/service/src/parentchain_handler.rs +++ b/service/src/parentchain_handler.rs @@ -30,7 +30,7 @@ use log::*; use my_node_runtime::Header; use sp_consensus_grandpa::VersionedAuthorityList; use sp_runtime::traits::Header as HeaderTrait; -use std::{cmp::min, sync::Arc, thread, time::Duration}; +use std::{cmp::min, sync::Arc}; use substrate_api_client::ac_primitives::{Block, Header as HeaderT}; const BLOCK_SYNC_BATCH_SIZE: u32 = 1000; @@ -227,8 +227,6 @@ where while last_synced_header.number() < until_header.number() { last_synced_header = self.sync_parentchain(last_synced_header)?; trace!("[{:?}] synced block number: {}", id, last_synced_header.number); - // fast polling is useless because we only loop here if the target block hasn't been finalized yet - thread::sleep(Duration::from_millis(1000)); } self.trigger_parentchain_block_import()?; From 42fac49dd288841b5a5c0b2bf123c41cc826035e Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Tue, 24 Oct 2023 11:46:46 +0200 Subject: [PATCH 23/26] fix diagram bug --- DESIGN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESIGN.md b/DESIGN.md index c2529e5473..8d579d96b7 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -64,7 +64,7 @@ sequenceDiagram validateer_1 ->> integritee_network: register_sgx_enclave() - validateer_1 ->> integritee_network: register_sgx_enclave() + validateer_2 ->> integritee_network: register_sgx_enclave() validateer_2 ->> validateer_1: sidechain_fetchBlocksFromPeer() From f5acb2d5597b4105b27f354c7c16fe0974c2469f Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Tue, 24 Oct 2023 15:10:56 +0200 Subject: [PATCH 24/26] fix mock test --- service/src/tests/mocks/enclave_api_mock.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/service/src/tests/mocks/enclave_api_mock.rs b/service/src/tests/mocks/enclave_api_mock.rs index 20baa73058..bb7d47acde 100644 --- a/service/src/tests/mocks/enclave_api_mock.rs +++ b/service/src/tests/mocks/enclave_api_mock.rs @@ -25,6 +25,7 @@ use itc_parentchain::primitives::{ use itp_enclave_api::{enclave_base::EnclaveBase, sidechain::Sidechain, EnclaveResult}; use itp_settings::worker::MR_ENCLAVE_SIZE; use itp_storage::StorageProof; +use itp_types::ShardIdentifier; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::ed25519; @@ -60,7 +61,7 @@ impl EnclaveBase for EnclaveMock { unimplemented!() } - fn init_proxied_shard_vault(&self, _shard: Vec) -> EnclaveResult<()> { + fn init_proxied_shard_vault(&self, _shard: &ShardIdentifier) -> EnclaveResult<()> { unimplemented!() } @@ -84,7 +85,7 @@ impl EnclaveBase for EnclaveMock { unreachable!() } - fn get_ecc_vault_pubkey(&self) -> EnclaveResult { + fn get_ecc_vault_pubkey(&self, shard: &ShardIdentifier) -> EnclaveResult { unreachable!() } From 6e03fff00c5e9ecca2b6d60fa180e1877f415437 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Wed, 25 Oct 2023 17:04:41 +0200 Subject: [PATCH 25/26] avoid panic if add_shard_vault_proxy fails --- enclave-runtime/src/shard_vault.rs | 7 +++++-- enclave-runtime/src/tls_ra/tls_ra_server.rs | 8 ++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/enclave-runtime/src/shard_vault.rs b/enclave-runtime/src/shard_vault.rs index 5045620eaa..860f2ef56d 100644 --- a/enclave-runtime/src/shard_vault.rs +++ b/enclave-runtime/src/shard_vault.rs @@ -167,7 +167,10 @@ pub(crate) fn init_proxied_shard_vault_internal(shard: ShardIdentifier) -> Encla Ok(()) } -pub(crate) fn add_shard_vault_proxy(shard: ShardIdentifier, proxy: AccountId) -> EnclaveResult<()> { +pub(crate) fn add_shard_vault_proxy( + shard: ShardIdentifier, + proxy: &AccountId, +) -> EnclaveResult<()> { let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; if !state_handler.shard_exists(&shard).unwrap() { return Err(Error::Other("shard not initialized".into())) @@ -186,7 +189,7 @@ pub(crate) fn add_shard_vault_proxy(shard: ShardIdentifier, proxy: AccountId) -> let add_proxy_call = OpaqueCall::from_tuple(&( node_metadata_repo.get_from_metadata(|m| m.add_proxy_call_indexes())??, - Address::from(proxy), + Address::from(proxy.clone()), ProxyType::Any, 0u32, // delay )); diff --git a/enclave-runtime/src/tls_ra/tls_ra_server.rs b/enclave-runtime/src/tls_ra/tls_ra_server.rs index 7d6b088e46..b03c1f59ae 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_server.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -98,8 +98,12 @@ where hex::encode(request.account.clone()), request.shard ); - add_shard_vault_proxy(request.shard, request.account)?; - + if let Err(e) = add_shard_vault_proxy(request.shard, &request.account) { + // we can't be sure that registering the proxy will succeed onchain at this point, + // therefore we can accept an error here as the client has to verify anyway and + // retry if it failed + error!("failed to add shard vault proxy for {:?}: {:?}", request.account, e); + }; Ok(()) } From 2109bd28ef94bf3102c9496f057a2f2e4847c4b9 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Thu, 26 Oct 2023 09:20:15 +0200 Subject: [PATCH 26/26] skip shard vault stuff for offchain-worker --- service/src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/service/src/main.rs b/service/src/main.rs index e88f1d1176..750ff83507 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -594,7 +594,9 @@ fn start_worker( }) .unwrap(); - if let Ok(shard_vault) = enclave.get_ecc_vault_pubkey(shard) { + if WorkerModeProvider::worker_mode() == WorkerMode::OffChainWorker { + info!("skipping shard vault check because not yet supported for offchain worker"); + } else if let Ok(shard_vault) = enclave.get_ecc_vault_pubkey(shard) { println!( "shard vault account is already initialized in state: {}", shard_vault.to_ss58check()