diff --git a/Cargo.lock b/Cargo.lock index bd2b391846..a20734ea87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3888,6 +3888,7 @@ dependencies = [ "hex 0.3.2", "hyper", "ipfs-api", + "lazy_static", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "multihash", "pallet-balances", diff --git a/enclave/Enclave.edl b/enclave/Enclave.edl index e907602247..cf6a0b227e 100644 --- a/enclave/Enclave.edl +++ b/enclave/Enclave.edl @@ -48,7 +48,6 @@ enclave { public sgx_status_t sync_chain_relay( [in, size=blocks_size] uint8_t* blocks, size_t blocks_size, [in] uint32_t* nonce, - [in, size=node_url_size] uint8_t* node_url, size_t node_url_size, [out, size=unchecked_extrinsic_size] uint8_t* unchecked_extrinsic, size_t unchecked_extrinsic_size ); @@ -64,7 +63,7 @@ enclave { public sgx_status_t perform_ra( [in, size=genesis_hash_size] uint8_t* genesis_hash, uint32_t genesis_hash_size, [in] uint32_t* nonce, - [in, size=url_size] uint8_t* url, uint32_t url_size, + [in, size=w_url_size] uint8_t* w_url, uint32_t w_url_size, [out, size=unchecked_extrinsic_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_size ); @@ -110,7 +109,6 @@ enclave { sgx_status_t ocall_worker_request( [in, size = req_size] uint8_t * request, uint32_t req_size, - [in, size = node_url_size] uint8_t * node_url, uint32_t node_url_size, [out, size = resp_size] uint8_t * response, uint32_t resp_size ); }; diff --git a/enclave/src/attestation.rs b/enclave/src/attestation.rs index 32c6f7131b..955a6b4a86 100644 --- a/enclave/src/attestation.rs +++ b/enclave/src/attestation.rs @@ -609,8 +609,8 @@ pub unsafe extern "C" fn perform_ra( genesis_hash: *const u8, genesis_hash_size: u32, nonce: *const u32, - url: *const u8, - url_size: u32, + w_url: *const u8, + w_url_size: u32, unchecked_extrinsic: *mut u8, unchecked_extrinsic_size: u32, ) -> sgx_status_t { @@ -625,7 +625,7 @@ pub unsafe extern "C" fn perform_ra( info!(" [Enclave] Compose extrinsic"); let genesis_hash_slice = slice::from_raw_parts(genesis_hash, genesis_hash_size as usize); //let mut nonce_slice = slice::from_raw_parts(nonce, nonce_size as usize); - let url_slice = slice::from_raw_parts(url, url_size as usize); + let url_slice = slice::from_raw_parts(w_url, w_url_size as usize); let extrinsic_slice = slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); let signer = match ed25519::unseal_pair() { diff --git a/enclave/src/lib.rs b/enclave/src/lib.rs index 73204e509a..7c96ff00a9 100644 --- a/enclave/src/lib.rs +++ b/enclave/src/lib.rs @@ -223,6 +223,34 @@ pub unsafe extern "C" fn get_state( Err(status) => return status, }; + let validator = match io::light_validation::unseal() { + Ok(val) => val, + Err(e) => return e, + }; + + let latest_header = validator.latest_header(validator.num_relays).unwrap(); + + debug!("Update STF storage!"); + let requests: Vec = + Stf::get_storage_hashes_to_update_for_getter(&tusted_getter_signed) + .into_iter() + .map(|key| WorkerRequest::ChainStorage(key, Some(latest_header.hash()))) + .collect(); + + if !requests.is_empty() { + let responses: Vec>> = match worker_request(requests) { + Ok(resp) => resp, + Err(e) => return e, + }; + + let update_map = match verify_worker_responses(responses, latest_header) { + Ok(map) => map, + Err(e) => return e, + }; + + Stf::update_storage(&mut state, &update_map); + } + debug!("calling into STF to get state"); let value_opt = Stf::get_state(&mut state, tusted_getter_signed.getter); @@ -286,13 +314,10 @@ pub unsafe extern "C" fn sync_chain_relay( blocks: *const u8, blocks_size: usize, nonce: *const u32, - node_url: *const u8, - node_url_size: usize, unchecked_extrinsic: *mut u8, unchecked_extrinsic_size: usize, ) -> sgx_status_t { info!("Syncing chain relay!"); - let node_url = slice::from_raw_parts(node_url, node_url_size as usize); let mut blocks_slice = slice::from_raw_parts(blocks, blocks_size); let xt_slice = slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size); @@ -323,12 +348,12 @@ pub unsafe extern "C" fn sync_chain_relay( return sgx_status_t::SGX_ERROR_UNEXPECTED; } - match scan_block_for_relevant_xt(&signed_block.block, node_url) { + match scan_block_for_relevant_xt(&signed_block.block) { Ok(c) => calls.extend(c.into_iter()), Err(_) => error!("Error executing relevant extrinsics"), }; - if update_states(signed_block.block.header, node_url).is_err() { + if update_states(signed_block.block.header).is_err() { error!("Error performing state updates upon block import") } } @@ -340,14 +365,18 @@ pub unsafe extern "C" fn sync_chain_relay( sgx_status_t::SGX_SUCCESS } -pub fn update_states(header: Header, node_url: &[u8]) -> SgxResult<()> { +pub fn update_states(header: Header) -> SgxResult<()> { debug!("Update STF storage upon block import!"); - let requests = Stf::storage_hashes_to_update_on_block() + let requests: Vec = Stf::storage_hashes_to_update_on_block() .into_iter() .map(|key| WorkerRequest::ChainStorage(key, Some(header.hash()))) .collect(); - let responses: Vec>> = worker_request(requests, node_url)?; + if requests.is_empty() { + return Ok(()); + } + + let responses: Vec>> = worker_request(requests)?; let update_map = verify_worker_responses(responses, header)?; let shards = state::list_shards()?; @@ -361,7 +390,7 @@ pub fn update_states(header: Header, node_url: &[u8]) -> SgxResult<()> { } /// Scans blocks for extrinsics that ask the enclave to execute some actions. -pub fn scan_block_for_relevant_xt(block: &Block, node_url: &[u8]) -> SgxResult> { +pub fn scan_block_for_relevant_xt(block: &Block) -> SgxResult> { debug!("Scanning blocks for relevant xt"); let mut calls = Vec::::new(); for xt_opaque in block.extrinsics.iter() { @@ -380,9 +409,7 @@ pub fn scan_block_for_relevant_xt(block: &Block, node_url: &[u8]) -> SgxResult::decode(&mut xt_opaque.0.encode().as_slice()) { if xt.function.0 == [SUBSRATEE_REGISTRY_MODULE, CALL_WORKER] { - if let Err(e) = - handle_call_worker_xt(&mut calls, xt, block.header.clone(), node_url) - { + if let Err(e) = handle_call_worker_xt(&mut calls, xt, block.header.clone()) { error!("Error performing worker call: Error: {:?}", e); } } @@ -403,6 +430,7 @@ fn handle_shield_funds_xt( let mut state = if state::exists(&shard) { state::load(&shard)? } else { + state::init_shard(&shard)?; Stf::init_state() }; @@ -442,7 +470,6 @@ fn handle_call_worker_xt( calls: &mut Vec, xt: UncheckedExtrinsicV4, header: Header, - node_url: &[u8], ) -> SgxResult<()> { let (call, request) = xt.function; let (shard, cyphertext) = (request.shard, request.cyphertext); @@ -476,6 +503,7 @@ fn handle_call_worker_xt( let mut state = if state::exists(&shard) { state::load(&shard)? } else { + state::init_shard(&shard)?; Stf::init_state() }; @@ -485,7 +513,7 @@ fn handle_call_worker_xt( .map(|key| WorkerRequest::ChainStorage(key, Some(header.hash()))) .collect(); - let responses: Vec>> = worker_request(requests, node_url)?; + let responses: Vec>> = worker_request(requests)?; let update_map = verify_worker_responses(responses, header)?; @@ -565,8 +593,6 @@ extern "C" { ret_val: *mut sgx_status_t, request: *const u8, req_size: u32, - node_url: *const u8, - node_url_size: u32, response: *mut u8, resp_size: u32, ) -> sgx_status_t; @@ -630,7 +656,6 @@ pub enum WorkerResponse { fn worker_request( req: Vec, - node_url: &[u8], ) -> SgxResult>> { let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; let mut resp: Vec = vec![0; 4196]; @@ -640,8 +665,6 @@ fn worker_request( &mut rt as *mut sgx_status_t, req.encode().as_ptr(), req.encode().len() as u32, - node_url.as_ptr(), - node_url.len() as u32, resp.as_mut_ptr(), resp.len() as u32, ) @@ -660,14 +683,13 @@ fn worker_request( fn test_ocall_worker_request() { info!("testing ocall_worker_request. Hopefully substraTEE-node is running..."); let mut requests = Vec::new(); - let node_url = format!("ws://{}:{}", "127.0.0.1", "9991").into_bytes(); requests.push(WorkerRequest::ChainStorage( storage_key("Balances", "TotalIssuance").0, None, )); - let mut resp: Vec>> = match worker_request(requests, node_url.as_ref()) { + let mut resp: Vec>> = match worker_request(requests) { Ok(response) => response, Err(e) => panic!("Worker response decode failed. Error: {:?}", e), }; diff --git a/enclave/src/state.rs b/enclave/src/state.rs index 3bd82e5286..e7b0bbbe5c 100644 --- a/enclave/src/state.rs +++ b/enclave/src/state.rs @@ -92,6 +92,10 @@ pub fn exists(shard: &ShardIdentifier) -> bool { .exists() } +pub fn init_shard(shard: &ShardIdentifier) -> SgxResult<()> { + fs::create_dir_all(format!("{}/{}", SHARDS_PATH, shard.encode().to_base58())).sgx_error() +} + fn read(path: &str) -> SgxResult> { let mut bytes = match io::read(path) { Ok(vec) => match vec.len() { diff --git a/stf/src/lib.rs b/stf/src/lib.rs index e29e515ac8..e20116e459 100644 --- a/stf/src/lib.rs +++ b/stf/src/lib.rs @@ -102,7 +102,7 @@ impl TrustedCall { } } -#[derive(Encode, Decode, Clone)] +#[derive(Encode, Decode, Clone, Debug)] #[allow(non_camel_case_types)] pub enum TrustedGetter { free_balance(AccountId), diff --git a/stf/src/sgx.rs b/stf/src/sgx.rs index e645d003b7..7c68a4519c 100644 --- a/stf/src/sgx.rs +++ b/stf/src/sgx.rs @@ -12,7 +12,7 @@ use sp_io::SgxExternalitiesTrait; use sp_runtime::traits::Dispatchable; use crate::{ - AccountId, State, Stf, TrustedCall, TrustedCallSigned, TrustedGetter, + AccountId, State, Stf, TrustedCall, TrustedCallSigned, TrustedGetter, TrustedGetterSigned, SUBSRATEE_REGISTRY_MODULE, UNSHIELD, }; use sp_core::blake2_256; @@ -204,6 +204,12 @@ impl Stf { key_hashes } + pub fn get_storage_hashes_to_update_for_getter(getter: &TrustedGetterSigned) -> Vec> { + let key_hashes = Vec::new(); + info!("No storage updates needed for getter: {:?}", getter.getter); // dummy. Is currently not needed + key_hashes + } + pub fn storage_hashes_to_update_on_block() -> Vec> { // let key_hashes = Vec::new(); // key_hashes.push(storage_value_key("dummy", "dummy")); diff --git a/worker/Cargo.toml b/worker/Cargo.toml index 70ef8295ba..0247494bcf 100644 --- a/worker/Cargo.toml +++ b/worker/Cargo.toml @@ -13,6 +13,7 @@ env_logger = "0.7" base58 = "0.1" rust-crypto = "0.2" clap = { version = "2.33", features = [ "yaml" ] } +lazy_static = "1.4.0" dirs = "1.0.2" serde = "1.0" diff --git a/worker/src/enclave/api.rs b/worker/src/enclave/api.rs index f9a7adde1b..a50cea771b 100644 --- a/worker/src/enclave/api.rs +++ b/worker/src/enclave/api.rs @@ -63,8 +63,6 @@ extern "C" { blocks: *const u8, blocks_size: usize, nonce: *const u32, - node_url: *const u8, - url_size: usize, unchecked_extrinsic: *mut u8, unchecked_extrinsic_size: usize, ) -> sgx_status_t; @@ -96,8 +94,8 @@ extern "C" { genesis_hash: *const u8, genesis_hash_size: u32, nonce: *const u32, - url: *const u8, - url_size: u32, + w_url: *const u8, + w_url_size: u32, unchecked_extrinsic: *mut u8, unchecked_extrinsic_size: u32, ) -> sgx_status_t; @@ -237,7 +235,6 @@ pub fn enclave_sync_chain_relay( eid: sgx_enclave_id_t, blocks: Vec, tee_nonce: u32, - node_url: &str, ) -> SgxResult> { let mut status = sgx_status_t::SGX_SUCCESS; @@ -251,8 +248,6 @@ pub fn enclave_sync_chain_relay( b.as_ptr(), b.len(), &tee_nonce, - node_url.as_ptr(), - node_url.len(), unchecked_extrinsics.as_mut_ptr(), EXTRINSIC_MAX_SIZE, ) @@ -366,7 +361,7 @@ pub fn enclave_perform_ra( eid: sgx_enclave_id_t, genesis_hash: Vec, nonce: u32, - url: Vec, + w_url: Vec, ) -> SgxResult> { let unchecked_extrinsic_size = EXTRINSIC_MAX_SIZE; let mut unchecked_extrinsic: Vec = vec![0u8; unchecked_extrinsic_size as usize]; @@ -378,8 +373,8 @@ pub fn enclave_perform_ra( genesis_hash.as_ptr(), genesis_hash.len() as u32, &nonce, - url.as_ptr(), - url.len() as u32, + w_url.as_ptr(), + w_url.len() as u32, unchecked_extrinsic.as_mut_ptr(), unchecked_extrinsic_size as u32, ) diff --git a/worker/src/main.rs b/worker/src/main.rs index 6380240d86..057e5b1037 100644 --- a/worker/src/main.rs +++ b/worker/src/main.rs @@ -20,7 +20,10 @@ use std::io::Write; use std::path::Path; use std::slice; use std::str; -use std::sync::mpsc::{channel, Sender}; +use std::sync::{ + mpsc::{channel, Sender}, + Mutex, +}; use std::thread; use sgx_types::*; @@ -28,6 +31,7 @@ use sgx_types::*; use base58::{FromBase58, ToBase58}; use clap::{load_yaml, App}; use codec::{Decode, Encode}; +use lazy_static::lazy_static; use log::*; use sp_core::{ crypto::{AccountId32, Ss58Codec}, @@ -69,6 +73,7 @@ fn main() { let node_port = matches.value_of("node-port").unwrap_or("9944"); let n_url = format!("{}:{}", node_ip, node_port); info!("Interacting with node on {}", n_url); + *NODE_URL.lock().unwrap() = n_url; let w_ip = matches.value_of("w-server").unwrap_or("127.0.0.1"); let w_port = matches.value_of("w-port").unwrap_or("2000"); @@ -96,7 +101,7 @@ fn main() { ShardIdentifier::from_slice(&mrenclave[..]) } }; - worker(&n_url, w_ip, w_port, mu_ra_port, &shard); + worker(w_ip, w_port, mu_ra_port, &shard); } else if matches.is_present("shielding-key") { info!("*** Get the public key from the TEE\n"); let enclave = enclave_init().unwrap(); @@ -204,7 +209,7 @@ fn main() { } } -fn worker(node_url: &str, w_ip: &str, w_port: &str, mu_ra_port: &str, shard: &ShardIdentifier) { +fn worker(w_ip: &str, w_port: &str, mu_ra_port: &str, shard: &ShardIdentifier) { info!("starting worker on shard {}", shard.encode().to_base58()); // ------------------------------------------------------------------------ // check for required files @@ -237,7 +242,8 @@ fn worker(node_url: &str, w_ip: &str, w_port: &str, mu_ra_port: &str, shard: &Sh // ------------------------------------------------------------------------ // start the substrate-api-client to communicate with the node - let mut api = Api::new(node_url.to_string()).set_signer(AccountKeyring::Alice.pair()); + let mut api = + Api::new(NODE_URL.lock().unwrap().clone()).set_signer(AccountKeyring::Alice.pair()); let genesis_hash = api.genesis_hash.as_bytes().to_vec(); let tee_accountid = enclave_account(eid); @@ -480,7 +486,7 @@ pub fn sync_chain_relay( let tee_accountid = enclave_account(eid); let tee_nonce = get_nonce(&api, &tee_accountid); - let xts = enclave_sync_chain_relay(eid, blocks_to_sync, tee_nonce, &api.url).unwrap(); + let xts = enclave_sync_chain_relay(eid, blocks_to_sync, tee_nonce).unwrap(); let extrinsics: Vec> = Decode::decode(&mut xts.as_slice()).unwrap(); info!( @@ -598,6 +604,11 @@ pub fn check_files() { } } +lazy_static! { + // todo: replace with &str, but use &str in api-client first + static ref NODE_URL: Mutex = Mutex::new("".to_string()); +} + /// # Safety /// /// FFI are always unsafe @@ -605,17 +616,14 @@ pub fn check_files() { pub unsafe extern "C" fn ocall_worker_request( request: *const u8, req_size: u32, - node_url: *const u8, - node_url_size: u32, response: *mut u8, resp_size: u32, ) -> sgx_status_t { debug!(" Entering ocall_worker_request"); let mut req_slice = slice::from_raw_parts(request, req_size as usize); let resp_slice = slice::from_raw_parts_mut(response, resp_size as usize); - let url_slice = slice::from_raw_parts(node_url, node_url_size as usize); - let api = Api::::new(String::from_utf8(url_slice.to_vec()).unwrap()); + let api = Api::::new(NODE_URL.lock().unwrap().clone()); let requests: Vec = Decode::decode(&mut req_slice).unwrap();