Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nonce validation to trusted calls #225

Merged
merged 33 commits into from
Apr 6, 2021
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
dd84146
add sgx nonce state update functions
haerdib Mar 10, 2021
227e90a
first steps towards rpc get nonce function
haerdib Mar 12, 2021
17b7cb8
change Index type to u64
haerdib Mar 12, 2021
079b54b
fix cli function and nonce type to Index
haerdib Mar 12, 2021
61117ab
simplify shard check
haerdib Mar 15, 2021
e0cddda
first compiling version with get_nonce()
haerdib Mar 15, 2021
7e967b2
rename direct call status to direct request status
haerdib Mar 15, 2021
e3dc456
replace hard coded nonce with get_nonce function
haerdib Mar 15, 2021
43f77fc
bug fix
haerdib Mar 15, 2021
deae382
add unittest
haerdib Mar 15, 2021
adb3a9b
add requires to ValidTransaction and enclave unit tests
haerdib Mar 19, 2021
5c89667
add ready tests
haerdib Mar 19, 2021
0a2d31f
add sensible validation_transaction in pool function
haerdib Mar 19, 2021
09eb3fc
add sensible transaction validation test
haerdib Mar 24, 2021
675d29e
fix pool unit tests
haerdib Mar 24, 2021
88f8284
unit test working
haerdib Mar 24, 2021
76103c9
fix unit tests
haerdib Mar 24, 2021
809adec
fix Index.. should be changed in sgx runtime to u64
haerdib Mar 24, 2021
c8a6bbb
working nonce validation and incrementation
haerdib Mar 25, 2021
2b0d79e
add invalid nonce unit test
haerdib Mar 25, 2021
5631f5c
decrease block building
haerdib Mar 25, 2021
87537c4
readd block.rs
haerdib Mar 29, 2021
bfe1974
rempve unnecessary encoding of account_data and account_nonce function
haerdib Mar 30, 2021
a87fb5e
change read_shard matching to simple unwrap()
haerdib Mar 30, 2021
4de488b
change harde coded max future tops in pool to constant
haerdib Mar 30, 2021
26f04cd
make validate_nonce better readable
haerdib Mar 30, 2021
2343398
add error handling to increment nonce
haerdib Mar 30, 2021
fa1d6f8
add FIXME to increment nonce and remove possible panic
haerdib Mar 31, 2021
f81e058
add FIXME: test feature for account_data function
haerdib Mar 31, 2021
4e6f2bc
move increment nonce outside of match statement
haerdib Mar 31, 2021
ce67544
Trusted getter for nonce (#232)
haerdib Mar 31, 2021
3bb6953
Merge branch 'sidechain' into add-nonce
haerdib Mar 31, 2021
7f33b2a
move validate nonce outside of match call statement
haerdib Apr 6, 2021
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
23 changes: 7 additions & 16 deletions client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use substrate_api_client::{
use substrate_client_keystore::LocalKeystore;
use substratee_stf::{ShardIdentifier, TrustedCallSigned, TrustedOperation};
use substratee_worker_api::direct_client::DirectApi as DirectWorkerApi;
use substratee_worker_primitives::{DirectCallStatus, RpcRequest, RpcResponse, RpcReturnValue};
use substratee_worker_primitives::{DirectRequestStatus, RpcRequest, RpcResponse, RpcReturnValue};

type AccountPublic = <Signature as Verify>::Signer;
const KEYSTORE_PATH: &str = "my_keystore";
Expand Down Expand Up @@ -459,10 +459,7 @@ fn get_state(matches: &ArgMatches<'_>, getter: TrustedOperation) -> Option<Vec<u
return None;
}
};
let shard = match read_shard(matches) {
Ok(shard) => shard,
Err(e) => panic!(e),
};
let shard = read_shard(matches).unwrap();

// compose jsonrpc call
let data = Request {
Expand All @@ -484,7 +481,7 @@ fn get_state(matches: &ArgMatches<'_>, getter: TrustedOperation) -> Option<Vec<u
Ok(response) => {
let response: RpcResponse = serde_json::from_str(&response).unwrap();
if let Ok(return_value) = RpcReturnValue::decode(&mut response.result.as_slice()) {
if return_value.status == DirectCallStatus::Error {
if return_value.status == DirectRequestStatus::Error {
println!(
"[Error] {}",
String::decode(&mut return_value.value.as_slice()).unwrap()
Expand Down Expand Up @@ -532,10 +529,7 @@ fn send_request(matches: &ArgMatches<'_>, call: TrustedCallSigned) -> Option<Vec
}
};

let shard = match read_shard(matches) {
Ok(shard) => shard,
Err(e) => panic!(e),
};
let shard = read_shard(matches).unwrap();

let arg_signer = matches.value_of("xt-signer").unwrap();
let signer = get_pair_from_str(arg_signer);
Expand Down Expand Up @@ -619,10 +613,7 @@ fn send_direct_request(
return None;
}
};
let shard = match read_shard(matches) {
Ok(shard) => shard,
Err(e) => panic!(e),
};
let shard = read_shard(matches).unwrap();

// compose jsonrpc call
let data = Request {
Expand Down Expand Up @@ -650,13 +641,13 @@ fn send_direct_request(
let response: RpcResponse = serde_json::from_str(&response).unwrap();
if let Ok(return_value) = RpcReturnValue::decode(&mut response.result.as_slice()) {
match return_value.status {
DirectCallStatus::Error => {
DirectRequestStatus::Error => {
if let Ok(value) = String::decode(&mut return_value.value.as_slice()) {
println!("[Error] {}", value);
}
return None;
}
DirectCallStatus::TrustedOperationStatus(status) => {
DirectRequestStatus::TrustedOperationStatus(status) => {
if let Ok(value) = Hash::decode(&mut return_value.value.as_slice()) {
println!("Trusted call {:?} is {:?}", value, status);
}
Expand Down
6 changes: 5 additions & 1 deletion enclave/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
limitations under the License.

*/
use substratee_stf::Index;

pub const RSA3072_SEALED_KEY_FILE: &str = "rsa3072_key_sealed.bin";
pub const SEALED_SIGNER_SEED_FILE: &str = "ed25519_key_sealed.bin";
Expand Down Expand Up @@ -49,5 +50,8 @@ pub static RUNTIME_SPEC_VERSION: u32 = 1;
pub static RUNTIME_TRANSACTION_VERSION: u32 = 1;

// timeouts for getter and call execution
pub static CALLTIMEOUT: i64 = 300; // timeout in ms
pub static CALLTIMEOUT: i64 = 300; // timeout in ms
pub static GETTERTIMEOUT: i64 = 300; // timeout in ms

// maximum allowed tops in the future pool per account
pub static MAX_ALLOWED_FUTURE_TOP: Index = 64;
5 changes: 3 additions & 2 deletions enclave/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ use substratee_stf::{

use rpc::author::{hash::TrustedOperationOrHash, Author, AuthorApi};
use rpc::worker_api_direct;
use rpc::{api::FillerChainApi, basic_pool::BasicPool};
use rpc::{api::SideChainApi, basic_pool::BasicPool};

mod aes;
mod attestation;
Expand Down Expand Up @@ -108,7 +108,7 @@ pub enum Timeout {
}

pub type Hash = sp_core::H256;
type BPool = BasicPool<FillerChainApi<Block>, Block>;
type BPool = BasicPool<SideChainApi<Block>, Block>;

#[no_mangle]
pub unsafe extern "C" fn init() -> sgx_status_t {
Expand Down Expand Up @@ -588,6 +588,7 @@ fn execute_top_pool_calls(
Ok((calls, _)) => calls,
Err(_) => return Err(sgx_status_t::SGX_ERROR_UNEXPECTED),
};
debug!("Got following trusted calls from pool: {:?}", trusted_calls);
// call execution
for trusted_call_signed in trusted_calls.into_iter() {
match handle_trusted_worker_call(
Expand Down
44 changes: 29 additions & 15 deletions enclave/src/rpc/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,41 +21,49 @@ extern crate alloc;
use alloc::{boxed::Box, vec::Vec};
use log::*;

use codec::Encode;
use codec::{Encode, Decode};
use jsonrpc_core::futures::future::{ready, Future, Ready};
use std::{marker::PhantomData, pin::Pin};

use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, Hash as HashT, Header as HeaderT},
transaction_validity::{
TransactionValidity, TransactionValidityError, UnknownTransaction, ValidTransaction,
TransactionValidity, TransactionValidityError, UnknownTransaction,
InvalidTransaction, ValidTransaction,
},
};

use crate::top_pool::pool::{ChainApi, ExtrinsicHash, NumberFor};
use crate::top_pool::primitives::TrustedOperationSource;
use crate::state;

use substratee_stf::{Getter, TrustedOperation as StfTrustedOperation};
use substratee_stf::{Getter, TrustedOperation as StfTrustedOperation, AccountId,
Index, ShardIdentifier, Stf};
use substratee_worker_primitives::BlockHash as SidechainBlockHash;

use crate::rpc::error;

use crate::constants::MAX_ALLOWED_FUTURE_TOP;

/// Future that resolves to account nonce.
pub type Result<T> = core::result::Result<T, ()>;

/// The operation pool logic for full client.
pub struct FillerChainApi<Block> {
pub struct SideChainApi<Block> {
_marker: PhantomData<Block>,
}

impl<Block> FillerChainApi<Block> {
impl<Block> SideChainApi<Block> {
/// Create new operation pool logic.
pub fn new() -> Self {
FillerChainApi {
SideChainApi {
_marker: Default::default(),
}
}
}

impl<Block> ChainApi for FillerChainApi<Block>
impl<Block> ChainApi for SideChainApi<Block>
where
Block: BlockT,
{
Expand All @@ -71,17 +79,23 @@ where

fn validate_transaction(
&self,
_at: &BlockId<Self::Block>,
_source: TrustedOperationSource,
uxt: StfTrustedOperation,
_shard: ShardIdentifier,
) -> Self::ValidationFuture {
let operation = match uxt {
StfTrustedOperation::direct_call(call) => ValidTransaction {
priority: 1 << 20,
requires: vec![],
provides: vec![vec![call.nonce as u8], call.signature.encode()],
longevity: 3,
propagate: true,
StfTrustedOperation::direct_call(signed_call) => {
let from = signed_call.call.account();
let requires = vec![];
let provides = vec![from.encode()];

ValidTransaction {
priority: 1 << 20,
requires: requires,
provides: provides,
longevity: 64,
propagate: true,
}
},
StfTrustedOperation::get(getter) => match getter {
Getter::public(_) => {
Expand All @@ -93,7 +107,7 @@ where
priority: 1 << 20,
requires: vec![],
provides: vec![trusted_getter.signature.encode()],
longevity: 3,
longevity: 64,
propagate: true,
},
},
Expand Down
22 changes: 8 additions & 14 deletions enclave/src/rpc/author/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,10 @@ where
shard: ShardIdentifier,
) -> FutureResult<TxHash<P>, RpcError> {
// check if shard already exists
let shards = match state::list_shards() {
Ok(shards) => shards,
Err(_) => return Box::pin(ready(Err(ClientError::InvalidShard.into()))),
};
if !shards.contains(&shard) {
return Box::pin(ready(Err(ClientError::InvalidShard.into())));
}
if !state::exists(&shard) {
//FIXME: Should this be an error? -> Issue error handling
return Box::pin(ready(Err(ClientError::InvalidShard.into())))
}
// decrypt call
let rsa_keypair = rsa3072::unseal_pair().unwrap();
let request_vec: Vec<u8> = match rsa3072::decrypt(&ext.as_slice(), &rsa_keypair) {
Expand Down Expand Up @@ -237,13 +234,10 @@ where

fn watch_top(&self, ext: Vec<u8>, shard: ShardIdentifier) -> FutureResult<TxHash<P>, RpcError> {
// check if shard already exists
let shards = match state::list_shards() {
Ok(shards) => shards,
Err(_) => return Box::pin(ready(Err(ClientError::InvalidShard.into()))),
};
if !shards.contains(&shard) {
return Box::pin(ready(Err(ClientError::InvalidShard.into())));
}
if !state::exists(&shard) {
//FIXME: Should this be an error? -> Issue error handling
return Box::pin(ready(Err(ClientError::InvalidShard.into())))
}
// decrypt call
let rsa_keypair = rsa3072::unseal_pair().unwrap();
let request_vec: Vec<u8> = match rsa3072::decrypt(&ext.as_slice(), &rsa_keypair) {
Expand Down
33 changes: 16 additions & 17 deletions enclave/src/rpc/worker_api_direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use codec::{Decode, Encode};
use log::*;

use crate::rpc::{
api::FillerChainApi,
api::SideChainApi,
author::{Author, AuthorApi},
basic_pool::BasicPool,
};
Expand All @@ -57,7 +57,7 @@ use chain_relay::Block;

use substratee_node_primitives::Request;
use substratee_worker_primitives::RpcReturnValue;
use substratee_worker_primitives::{TrustedOperationStatus, DirectCallStatus};
use substratee_worker_primitives::{TrustedOperationStatus, DirectRequestStatus};

use crate::utils::write_slice_and_whitespace_pad;
use crate::rsa3072;
Expand All @@ -84,9 +84,9 @@ extern "C" {
#[no_mangle]
// initialise tx pool and store within static atomic pointer
pub unsafe extern "C" fn initialize_pool() -> sgx_status_t {
let api = Arc::new(FillerChainApi::new());
let api = Arc::new(SideChainApi::new());
let tx_pool = BasicPool::create(PoolOptions::default(), api);
let pool_ptr = Arc::new(SgxMutex::<BasicPool<FillerChainApi<Block>, Block>>::new(
let pool_ptr = Arc::new(SgxMutex::<BasicPool<SideChainApi<Block>, Block>>::new(
tx_pool,
));
let ptr = Arc::into_raw(pool_ptr);
Expand All @@ -95,9 +95,9 @@ pub unsafe extern "C" fn initialize_pool() -> sgx_status_t {
sgx_status_t::SGX_SUCCESS
}

pub fn load_top_pool() -> Option<&'static SgxMutex<BasicPool<FillerChainApi<Block>, Block>>> {
pub fn load_top_pool() -> Option<&'static SgxMutex<BasicPool<SideChainApi<Block>, Block>>> {
let ptr = GLOBAL_TX_POOL.load(Ordering::SeqCst)
as *mut SgxMutex<BasicPool<FillerChainApi<Block>, Block>>;
as *mut SgxMutex<BasicPool<SideChainApi<Block>, Block>>;
if ptr.is_null() {
None
} else {
Expand Down Expand Up @@ -134,7 +134,7 @@ fn compute_encoded_return_error(error_msg: String) -> Vec<u8> {
let return_value = RpcReturnValue {
value: error_msg.encode(),
do_watch: false,
status: DirectCallStatus::Error,
status: DirectRequestStatus::Error,
};
return_value.encode()
}
Expand Down Expand Up @@ -173,7 +173,7 @@ fn init_io_handler() -> IoHandler {
RpcReturnValue {
do_watch: true,
value: hash_value.encode(),
status: DirectCallStatus::TrustedOperationStatus(TrustedOperationStatus::Submitted),
status: DirectRequestStatus::TrustedOperationStatus(TrustedOperationStatus::Submitted),
}.encode()
},
Err(rpc_error) => compute_encoded_return_error(rpc_error.message)
Expand Down Expand Up @@ -220,7 +220,7 @@ fn init_io_handler() -> IoHandler {
RpcReturnValue {
do_watch: false,
value: hash_value.encode(),
status: DirectCallStatus::TrustedOperationStatus(TrustedOperationStatus::Submitted),
status: DirectRequestStatus::TrustedOperationStatus(TrustedOperationStatus::Submitted),
}.encode()
},
Err(rpc_error) => compute_encoded_return_error(rpc_error.message)
Expand Down Expand Up @@ -259,34 +259,34 @@ fn init_io_handler() -> IoHandler {
};
if let Ok(vec_of_operations) = author.pending_tops(shard) {
retrieved_operations.push(vec_of_operations);
}
}
}
let json_value = RpcReturnValue {
do_watch: false,
value: retrieved_operations.encode(),
status: DirectCallStatus::Ok,
status: DirectRequestStatus::Ok,
};
Ok(json!(json_value.encode()))
}
Err(e) => {
let error_msg: String = format!("Could not retrieve pending calls due to: {}", e);
Ok(json!(compute_encoded_return_error(error_msg)))
}
}
}
});

// author_getShieldingKey
let rsa_pubkey_name: &str = "author_getShieldingKey";
rpc_methods_vec.push(rsa_pubkey_name);
io.add_sync_method(rsa_pubkey_name, move |_: Params| {
io.add_sync_method(rsa_pubkey_name, move |_: Params| {
let rsa_pubkey = match rsa3072::unseal_pubkey() {
Ok(key) => key,
Err(status) => {
let error_msg: String = format!("Could not get rsa pubkey due to: {}", status);
return Ok(json!(compute_encoded_return_error(error_msg)))
},
};

let rsa_pubkey_json = match serde_json::to_string(&rsa_pubkey) {
Ok(k) => k,
Err(x) => {
Expand All @@ -296,11 +296,10 @@ fn init_io_handler() -> IoHandler {
return Ok(json!(compute_encoded_return_error(error_msg)))
},
};
let json_value = RpcReturnValue::new(rsa_pubkey_json.encode(), false, DirectCallStatus::Ok);
Ok(json!(json_value.encode()))
let json_value = RpcReturnValue::new(rsa_pubkey_json.encode(), false, DirectRequestStatus::Ok);
Ok(json!(json_value.encode()))
});


// chain_subscribeAllHeads
let chain_subscribe_all_heads_name: &str = "chain_subscribeAllHeads";
rpc_methods_vec.push(chain_subscribe_all_heads_name);
Expand Down
Loading