Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions enclave/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2639,6 +2639,7 @@ dependencies = [
"cid",
"derive_more",
"env_logger",
"frame-support",
"httparse",
"ipfs-unixfs",
"itertools",
Expand Down
6 changes: 6 additions & 0 deletions enclave/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ features = ["disable_oom", "disable_panic_handler", "disable_allocator", "sgx"]
git = "https://github.com/apache/teaclave-sgx-sdk.git"
rev = "v1.1.3"

[dependencies.frame-support]
git = "https://github.com/paritytech/substrate.git"
branch = "master"
version = "3.0.0"
default-features = false

[dependencies.sp-core]
git = "https://github.com/paritytech/substrate.git"
branch = "master"
Expand Down
33 changes: 33 additions & 0 deletions enclave/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use derive_more::{Display, From};
use sgx_types::sgx_status_t;
use crate::rpc;

use std::result::Result as StdResult;

pub type Result<T> = StdResult<T, Error>;

#[derive(Debug, Display, From)]
pub enum Error {
Rpc(rpc::error::Error),
Codec(codec::Error),
Sgx(sgx_status_t)
}

impl From<Error> for sgx_status_t {
Copy link
Contributor Author

@clangenb clangenb Jul 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementing From gives you Into for free, which is what we actually need.

/// return sgx_status for top level enclave functions
fn from(error: Error) -> sgx_status_t {
match error {
Error::Sgx(status) => status,
_=> {
log::warn!("Tried extracting sgx_status from non-sgx error: {:?}", error);
sgx_status_t::SGX_ERROR_UNEXPECTED
}
}
}
}

impl<T> From<Error> for StdResult<T, Error> {
fn from(error: Error) -> StdResult<T, Error> {
Err(error)
}
}
92 changes: 41 additions & 51 deletions enclave/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extern crate sgx_tstd as std;

use base58::ToBase58;

use sgx_types::{sgx_epid_group_id_t, sgx_status_t, sgx_target_info_t, SgxResult};
use sgx_types::{sgx_epid_group_id_t, sgx_status_t, sgx_target_info_t};

use substrate_api_client::compose_extrinsic_offline;
use substratee_node_primitives::{CallWorkerFn, ShieldFundsFn};
Expand Down Expand Up @@ -61,6 +61,7 @@ use chain_relay::{
storage_proof::{StorageProof, StorageProofChecker},
Block, Header, LightValidation,
};
use frame_support::ensure;
use sp_runtime::OpaqueExtrinsic;
use sp_runtime::{generic::SignedBlock, traits::Header as HeaderT};
use substrate_api_client::extrinsic::xt_primitives::UncheckedExtrinsicV4;
Expand Down Expand Up @@ -91,6 +92,7 @@ pub mod rpc;
pub mod tests;
pub mod tls_ra;
pub mod top_pool;
pub mod error;

use substratee_settings::node::{BLOCK_CONFIRMED, CALL_CONFIRMED, RUNTIME_SPEC_VERSION, RUNTIME_TRANSACTION_VERSION, SUBSTRATEE_REGISTRY_MODULE, CALL_WORKER, SHIELD_FUNDS, REGISTER_ENCLAVE};
use substratee_settings::enclave::{CALL_TIMEOUT, GETTER_TIMEOUT};
Expand All @@ -107,6 +109,8 @@ pub enum Timeout {
pub type Hash = sp_core::H256;
type BPool = BasicPool<SideChainApi<Block>, Block>;

use crate::error::{Error, Result};

#[no_mangle]
pub unsafe extern "C" fn init() -> sgx_status_t {
// initialize the logging environment in the enclave
Expand Down Expand Up @@ -232,7 +236,7 @@ fn create_extrinsics(
validator: LightValidation,
calls_buffer: Vec<OpaqueCall>,
mut nonce: u32,
) -> SgxResult<Vec<Vec<u8>>> {
) -> Result<Vec<Vec<u8>>> {
// get information for composing the extrinsic
let signer = ed25519::unseal_pair()?;
debug!("Restored ECC pubkey: {:?}", signer.public());
Expand Down Expand Up @@ -313,12 +317,12 @@ pub unsafe extern "C" fn get_state(
if !requests.is_empty() {
let responses: Vec<WorkerResponse<Vec<u8>>> = match worker_request(requests) {
Ok(resp) => resp,
Err(e) => return e,
Err(e) => return e.into(),
};

let update_map = match verify_worker_responses(responses, latest_header) {
Ok(map) => map,
Err(e) => return e,
Err(e) => return e.into(),
};

Stf::update_storage(&mut state, &update_map);
Expand Down Expand Up @@ -486,7 +490,7 @@ pub unsafe extern "C" fn produce_blocks(
fn send_block_and_confirmation(
confirmations: Vec<Vec<u8>>,
signed_blocks: Vec<SignedSidechainBlock>,
) -> SgxResult<()> {
) -> Result<()> {
let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED;

let res = unsafe {
Expand All @@ -499,13 +503,8 @@ fn send_block_and_confirmation(
)
};

if rt != sgx_status_t::SGX_SUCCESS {
return Err(rt);
}

if res != sgx_status_t::SGX_SUCCESS {
return Err(res);
}
ensure!(rt == sgx_status_t::SGX_SUCCESS, rt);
ensure!(res == sgx_status_t::SGX_SUCCESS, res);

Ok(())
}
Expand Down Expand Up @@ -542,7 +541,7 @@ fn get_stf_state(

fn execute_top_pool_calls(
latest_onchain_header: Header,
) -> SgxResult<(Vec<OpaqueCall>, Vec<SignedSidechainBlock>)> {
) -> Result<(Vec<OpaqueCall>, Vec<SignedSidechainBlock>)> {
debug!("Executing pending pool operations");
let mut calls = Vec::<OpaqueCall>::new();
let mut blocks = Vec::<SignedSidechainBlock>::new();
Expand All @@ -552,7 +551,7 @@ fn execute_top_pool_calls(
Some(mutex) => mutex,
None => {
error!("Could not get mutex to pool");
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
return Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED).into();
}
};
let pool_guard: SgxMutexGuard<BPool> = pool_mutex.lock().unwrap();
Expand All @@ -570,10 +569,8 @@ fn execute_top_pool_calls(
let mut is_done = false;
for shard in shards.clone().into_iter() {
// retrieve trusted operations from pool
let trusted_getters = match author.get_pending_tops_separated(shard) {
Ok((_, getters)) => getters,
Err(_) => return Err(sgx_status_t::SGX_ERROR_UNEXPECTED),
};
let trusted_getters = author
.get_pending_tops_separated(shard)?.1;
for trusted_getter_signed in trusted_getters.into_iter() {
// get state
let value_opt = get_stf_state(trusted_getter_signed.clone(), shard);
Expand Down Expand Up @@ -626,10 +623,8 @@ fn execute_top_pool_calls(
let prev_state_hash = state::hash_of(state.state.clone())?;

// retrieve trusted operations from pool
let trusted_calls = match author.get_pending_tops_separated(shard) {
Ok((calls, _)) => calls,
Err(_) => return Err(sgx_status_t::SGX_ERROR_UNEXPECTED),
};
let trusted_calls = author.get_pending_tops_separated(shard)?.0;

debug!("Got following trusted calls from pool: {:?}", trusted_calls);
// call execution
for trusted_call_signed in trusted_calls.into_iter() {
Expand Down Expand Up @@ -708,21 +703,20 @@ pub fn compose_block_and_confirmation(
shard: ShardIdentifier,
state_hash_apriori: H256,
state: &mut StfState,
) -> SgxResult<(OpaqueCall, SignedSidechainBlock)> {
) -> Result<(OpaqueCall, SignedSidechainBlock)> {
let signer_pair = ed25519::unseal_pair()?;
let layer_one_head = latest_onchain_header.hash();

let block_number = match Stf::get_sidechain_block_number(state) {
Some(number) => number + 1,
None => return Err(sgx_status_t::SGX_ERROR_UNEXPECTED),
};
let block_number = Stf::get_sidechain_block_number(state)
.map(|n| n + 1)
.ok_or(Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED))?;

Stf::update_sidechain_block_number(state, block_number);

let block_number: u64 = block_number; //FIXME! Should be either u64 or u32! Not both..
let parent_hash = match Stf::get_last_block_hash(state) {
Some(hash) => hash,
None => return Err(sgx_status_t::SGX_ERROR_UNEXPECTED),
};
let parent_hash = Stf::get_last_block_hash(state)
.ok_or(Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED))?;

// hash previous of state
let state_hash_aposteriori = state::hash_of(state.state.clone())?;
let state_update = state.state_diff.clone().encode();
Expand Down Expand Up @@ -754,7 +748,7 @@ pub fn compose_block_and_confirmation(
Ok((opaque_call, signed_block))
}

pub fn update_states(header: Header) -> SgxResult<()> {
pub fn update_states(header: Header) -> Result<()> {
debug!("Update STF storage upon block import!");
let requests: Vec<WorkerRequest> = Stf::storage_hashes_to_update_on_block()
.into_iter()
Expand Down Expand Up @@ -809,7 +803,7 @@ pub fn update_states(header: Header) -> SgxResult<()> {
/// Scans blocks for extrinsics that ask the enclave to execute some actions.
/// Executes indirect invocation calls, aswell as shielding and unshielding calls
/// Returns all unshielding call confirmations as opaque calls
pub fn scan_block_for_relevant_xt(block: &Block) -> SgxResult<Vec<OpaqueCall>> {
pub fn scan_block_for_relevant_xt(block: &Block) -> Result<Vec<OpaqueCall>> {
debug!("Scanning block {} for relevant xt", block.header.number());
let mut opaque_calls = Vec::<OpaqueCall>::new();
for xt_opaque in block.extrinsics.iter() {
Expand Down Expand Up @@ -860,7 +854,7 @@ pub fn scan_block_for_relevant_xt(block: &Block) -> SgxResult<Vec<OpaqueCall>> {
fn handle_shield_funds_xt(
calls: &mut Vec<OpaqueCall>,
xt: UncheckedExtrinsicV4<ShieldFundsFn>,
) -> SgxResult<()> {
) -> Result<()> {
let (call, account_encrypted, amount, shard) = xt.function.clone();
info!("Found ShieldFunds extrinsic in block: \nCall: {:?} \nAccount Encrypted {:?} \nAmount: {} \nShard: {}",
call, account_encrypted, amount, shard.encode().to_base58(),
Expand Down Expand Up @@ -909,7 +903,7 @@ fn handle_shield_funds_xt(

fn decrypt_unchecked_extrinsic(
xt: UncheckedExtrinsicV4<CallWorkerFn>,
) -> SgxResult<(TrustedCallSigned, ShardIdentifier)> {
) -> Result<(TrustedCallSigned, ShardIdentifier)> {
let (call, request) = xt.function;
let (shard, cyphertext) = (request.shard, request.cyphertext);
debug!("Found CallWorker extrinsic in block: \nCall: {:?} \nRequest: \nshard: {}\ncyphertext: {:?}",
Expand All @@ -921,10 +915,9 @@ fn decrypt_unchecked_extrinsic(
debug!("decrypt the call");
let rsa_keypair = rsa3072::unseal_pair()?;
let request_vec = rsa3072::decrypt(&cyphertext, &rsa_keypair)?;
match TrustedCallSigned::decode(&mut request_vec.as_slice()) {
Ok(call) => Ok((call, shard)),
Err(_) => Err(sgx_status_t::SGX_ERROR_UNEXPECTED),
}

Ok(TrustedCallSigned::decode(&mut request_vec.as_slice())
.map(|call| (call, shard))?)
}

fn handle_trusted_worker_call(
Expand All @@ -934,7 +927,7 @@ fn handle_trusted_worker_call(
header: Header,
shard: ShardIdentifier,
author_pointer: Option<Arc<Author<&BPool>>>,
) -> SgxResult<Option<(H256, H256)>> {
) -> Result<Option<(H256, H256)>> {
debug!("query mrenclave of self");
let mrenclave = attestation::get_mrenclave_of_self()?;
debug!("MRENCLAVE of self is {}", mrenclave.m.to_base58());
Expand Down Expand Up @@ -1019,7 +1012,7 @@ fn handle_trusted_worker_call(
fn verify_worker_responses(
responses: Vec<WorkerResponse<Vec<u8>>>,
header: Header,
) -> SgxResult<HashMap<Vec<u8>, Option<Vec<u8>>>> {
) -> Result<HashMap<Vec<u8>, Option<Vec<u8>>>> {
let mut update_map = HashMap::new();
for response in responses.iter() {
match response {
Expand All @@ -1038,7 +1031,8 @@ fn verify_worker_responses(
// Todo: Why do they do it like that, we could supply the proof only and get the value from the proof directly??
if &actual != value {
error!("Wrong storage value supplied");
return Err(sgx_status_t::SGX_ERROR_UNEXPECTED);
// todo: return another error now that we introduced our custom error
return Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED).into();
}
update_map.insert(key.clone(), value.clone());
}
Expand Down Expand Up @@ -1098,7 +1092,7 @@ pub enum WorkerResponse<V: Encode + Decode> {

fn worker_request<V: Encode + Decode>(
req: Vec<WorkerRequest>,
) -> SgxResult<Vec<WorkerResponse<V>>> {
) -> Result<Vec<WorkerResponse<V>>> {
let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED;
let mut resp: Vec<u8> = vec![0; 4196 * 4];

Expand All @@ -1112,12 +1106,8 @@ fn worker_request<V: Encode + Decode>(
)
};

if rt != sgx_status_t::SGX_SUCCESS {
return Err(rt);
}
ensure!(rt == sgx_status_t::SGX_SUCCESS, rt);
ensure!(res == sgx_status_t::SGX_SUCCESS, res);

if res != sgx_status_t::SGX_SUCCESS {
return Err(res);
}
Ok(Decode::decode(&mut resp.as_slice()).unwrap())
}
Ok(Decode::decode(&mut resp.as_slice())?)
}