diff --git a/Cargo.lock b/Cargo.lock index aa42534e7c..b36058e33f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3221,6 +3221,7 @@ dependencies = [ "itp-sgx-crypto", "itp-sgx-runtime-primitives", "itp-stf-executor", + "itp-stf-interface", "itp-stf-primitives", "itp-test", "itp-top-pool-author", diff --git a/app-libs/parentchain-interface/src/integritee/event_filter.rs b/app-libs/parentchain-interface/src/integritee/event_filter.rs index c9ecb19a85..d403a93948 100644 --- a/app-libs/parentchain-interface/src/integritee/event_filter.rs +++ b/app-libs/parentchain-interface/src/integritee/event_filter.rs @@ -74,12 +74,7 @@ impl FilterEvents for FilterableEvents { .iter() .flatten() // flatten filters out the nones .filter_map(|ev| match ev.as_event::() { - Ok(maybe_event) => { - if maybe_event.is_none() { - log::warn!("Transfer event does not exist in parentchain metadata"); - }; - maybe_event - }, + Ok(maybe_event) => maybe_event, Err(e) => { log::error!("Could not decode event: {:?}", e); None diff --git a/app-libs/parentchain-interface/src/integritee/event_handler.rs b/app-libs/parentchain-interface/src/integritee/event_handler.rs index 8e01cbd978..3711b861c0 100644 --- a/app-libs/parentchain-interface/src/integritee/event_handler.rs +++ b/app-libs/parentchain-interface/src/integritee/event_handler.rs @@ -22,17 +22,9 @@ use ita_stf::{Getter, TrustedCall, TrustedCallSigned}; use itc_parentchain_indirect_calls_executor::error::Error; use itp_stf_primitives::{traits::IndirectExecutor, types::TrustedOperation}; use itp_types::parentchain::{AccountId, FilterEvents, HandleParentchainEvents, ParentchainError}; +use itp_utils::hex::hex_encode; use log::*; -type Seed = [u8; 32]; - -const ALICE_ENCODED: Seed = [ - 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, - 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, -]; - -const SHIELDING_ACCOUNT: AccountId = AccountId::new(ALICE_ENCODED); - pub struct ParentchainEventHandler {} impl ParentchainEventHandler { @@ -61,15 +53,22 @@ impl HandleParentchainEvents where Executor: IndirectExecutor, { - fn handle_events(executor: &Executor, events: impl FilterEvents) -> Result<(), Error> { + fn handle_events( + executor: &Executor, + events: impl FilterEvents, + vault_account: &AccountId, + ) -> Result<(), Error> { let filter_events = events.get_transfer_events(); - + trace!( + "filtering transfer events to shard vault account: {}", + hex_encode(vault_account.encode().as_slice()) + ); if let Ok(events) = filter_events { events .iter() - .filter(|&event| event.to == SHIELDING_ACCOUNT) + .filter(|&event| event.to == *vault_account) .try_for_each(|event| { - info!("transfer_event: {}", event); + info!("found transfer_event to vault account: {}", event); //call = IndirectCall::ShieldFunds(ShieldFundsArgs{ }) Self::shield_funds(executor, &event.from, event.amount) }) diff --git a/app-libs/parentchain-interface/src/target_a/event_handler.rs b/app-libs/parentchain-interface/src/target_a/event_handler.rs index 40dd0b8867..96cd3997ec 100644 --- a/app-libs/parentchain-interface/src/target_a/event_handler.rs +++ b/app-libs/parentchain-interface/src/target_a/event_handler.rs @@ -20,7 +20,7 @@ pub use ita_sgx_runtime::{Balance, Index}; use ita_stf::TrustedCallSigned; use itc_parentchain_indirect_calls_executor::error::Error; use itp_stf_primitives::traits::IndirectExecutor; -use itp_types::parentchain::{FilterEvents, HandleParentchainEvents}; +use itp_types::parentchain::{AccountId, FilterEvents, HandleParentchainEvents}; use log::*; pub struct ParentchainEventHandler {} @@ -30,7 +30,11 @@ impl HandleParentchainEvents where Executor: IndirectExecutor, { - fn handle_events(_executor: &Executor, _events: impl FilterEvents) -> Result<(), Error> { + fn handle_events( + _executor: &Executor, + _events: impl FilterEvents, + _vault_account: &AccountId, + ) -> Result<(), Error> { debug!("not handling any events for target A"); Ok(()) } diff --git a/app-libs/parentchain-interface/src/target_b/event_handler.rs b/app-libs/parentchain-interface/src/target_b/event_handler.rs index cb33206a8b..39a5555973 100644 --- a/app-libs/parentchain-interface/src/target_b/event_handler.rs +++ b/app-libs/parentchain-interface/src/target_b/event_handler.rs @@ -20,7 +20,7 @@ pub use ita_sgx_runtime::{Balance, Index}; use ita_stf::TrustedCallSigned; use itc_parentchain_indirect_calls_executor::error::Error; use itp_stf_primitives::traits::IndirectExecutor; -use itp_types::parentchain::{FilterEvents, HandleParentchainEvents}; +use itp_types::parentchain::{AccountId, FilterEvents, HandleParentchainEvents}; use log::*; pub struct ParentchainEventHandler {} @@ -30,7 +30,11 @@ impl HandleParentchainEvents where Executor: IndirectExecutor, { - fn handle_events(_executor: &Executor, _events: impl FilterEvents) -> Result<(), Error> { + fn handle_events( + _executor: &Executor, + _events: impl FilterEvents, + _vault_account: &AccountId, + ) -> Result<(), Error> { debug!("not handling any events for target B"); Ok(()) } diff --git a/app-libs/stf/src/stf_sgx.rs b/app-libs/stf/src/stf_sgx.rs index 88d14822cb..2257dc6dc0 100644 --- a/app-libs/stf/src/stf_sgx.rs +++ b/app-libs/stf/src/stf_sgx.rs @@ -26,11 +26,15 @@ use itp_stf_interface::{ parentchain_pallet::ParentchainPalletInterface, sudo_pallet::SudoPalletInterface, system_pallet::{SystemPalletAccountInterface, SystemPalletEventInterface}, - ExecuteCall, ExecuteGetter, InitState, StateCallInterface, StateGetterInterface, UpdateState, + ExecuteCall, ExecuteGetter, InitState, ShardVaultQuery, StateCallInterface, + StateGetterInterface, UpdateState, SHARD_VAULT_KEY, }; use itp_stf_primitives::{error::StfError, traits::TrustedCallVerification}; use itp_storage::storage_value_key; -use itp_types::{parentchain::ParentchainId, OpaqueCall}; +use itp_types::{ + parentchain::{AccountId, ParentchainId}, + OpaqueCall, +}; use itp_utils::stringify::account_id_to_string; use log::*; use sp_runtime::traits::StaticLookup; @@ -160,6 +164,17 @@ where } } +impl ShardVaultQuery for Stf +where + State: SgxExternalitiesTrait + Debug, +{ + fn get_vault(state: &mut State) -> Option { + state + .get(SHARD_VAULT_KEY.as_bytes()) + .and_then(|v| Decode::decode(&mut v.clone().as_slice()).ok()) + } +} + impl SudoPalletInterface for Stf where State: SgxExternalitiesTrait, diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 9437d4f4cb..6181bd71e7 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -119,6 +119,8 @@ pub enum CliError { TrustedOp { msg: String }, #[error("EvmReadCommands error: {:?}", msg)] EvmRead { msg: String }, + #[error("worker rpc api error: {:?}", msg)] + WorkerRpcApi { msg: String }, } pub type CliResult = Result; diff --git a/cli/src/trusted_base_cli/commands/get_shard.rs b/cli/src/trusted_base_cli/commands/get_shard.rs new file mode 100644 index 0000000000..6700d7b99b --- /dev/null +++ b/cli/src/trusted_base_cli/commands/get_shard.rs @@ -0,0 +1,67 @@ +/* + 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::{ + command_utils::get_worker_api_direct, trusted_cli::TrustedCli, Cli, CliError, CliResult, + CliResultOk, +}; +use base58::ToBase58; +use codec::{Decode, Encode}; + +use itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{RpcRequest, RpcResponse, RpcReturnValue}; + +use itp_types::DirectRequestStatus; +use itp_utils::FromHexPrefixed; +use log::*; + +use sp_core::H256; + +#[derive(Parser)] +pub struct GetShardCommand {} + +impl GetShardCommand { + pub(crate) fn run(&self, cli: &Cli, _trusted_args: &TrustedCli) -> CliResult { + let direct_api = get_worker_api_direct(cli); + let rpc_method = "author_getShard".to_owned(); + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call(rpc_method, vec![]).unwrap(); + let rpc_response_str = direct_api.get(&jsonrpc_call).unwrap(); + // Decode RPC response. + let rpc_response: RpcResponse = serde_json::from_str(&rpc_response_str) + .map_err(|err| CliError::WorkerRpcApi { msg: err.to_string() })?; + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode RpcReturnValue: {:?}", err); + CliError::WorkerRpcApi { msg: "failed to decode RpcReturnValue".to_string() } + })?; + + if rpc_return_value.status == DirectRequestStatus::Error { + println!("[Error] {}", String::decode(&mut rpc_return_value.value.as_slice()).unwrap()); + return Err(CliError::WorkerRpcApi { msg: "rpc error".to_string() }) + } + + let shard = H256::decode(&mut rpc_return_value.value.as_slice()) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode shard: {:?}", err); + CliError::WorkerRpcApi { msg: err.to_string() } + })?; + println!("{}", shard.encode().to_base58()); + Ok(CliResultOk::H256 { hash: shard }) + } +} diff --git a/cli/src/trusted_base_cli/commands/get_shard_vault.rs b/cli/src/trusted_base_cli/commands/get_shard_vault.rs new file mode 100644 index 0000000000..467ca78961 --- /dev/null +++ b/cli/src/trusted_base_cli/commands/get_shard_vault.rs @@ -0,0 +1,71 @@ +/* + 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::{ + command_utils::get_worker_api_direct, trusted_cli::TrustedCli, Cli, CliError, CliResult, + CliResultOk, +}; + +use codec::Decode; + +use itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{RpcRequest, RpcResponse, RpcReturnValue}; + +use itp_types::{AccountId, DirectRequestStatus}; +use itp_utils::FromHexPrefixed; +use log::*; + +use sp_core::crypto::Ss58Codec; + +#[derive(Parser)] +pub struct GetShardVaultCommand {} + +impl GetShardVaultCommand { + pub(crate) fn run(&self, cli: &Cli, _trusted_args: &TrustedCli) -> CliResult { + let direct_api = get_worker_api_direct(cli); + let rpc_method = "author_getShardVault".to_owned(); + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call(rpc_method, vec![]).unwrap(); + let rpc_response_str = direct_api.get(&jsonrpc_call).unwrap(); + // Decode RPC response. + let rpc_response: RpcResponse = serde_json::from_str(&rpc_response_str) + .map_err(|err| CliError::WorkerRpcApi { msg: err.to_string() })?; + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode RpcReturnValue: {:?}", err); + CliError::WorkerRpcApi { msg: "failed to decode RpcReturnValue".to_string() } + })?; + + if rpc_return_value.status == DirectRequestStatus::Error { + println!("[Error] {}", String::decode(&mut rpc_return_value.value.as_slice()).unwrap()); + return Err(CliError::WorkerRpcApi { msg: "rpc error".to_string() }) + } + + let vault = AccountId::decode(&mut rpc_return_value.value.as_slice()) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode vault account: {:?}", err); + CliError::WorkerRpcApi { msg: err.to_string() } + })?; + let vault_ss58 = vault.to_ss58check(); + println!("{}", vault_ss58); + Ok(CliResultOk::PubKeysBase58 { + pubkeys_sr25519: None, + pubkeys_ed25519: Some(vec![vault_ss58]), + }) + } +} diff --git a/cli/src/trusted_base_cli/commands/mod.rs b/cli/src/trusted_base_cli/commands/mod.rs index dbe7d36180..0687a4fe1d 100644 --- a/cli/src/trusted_base_cli/commands/mod.rs +++ b/cli/src/trusted_base_cli/commands/mod.rs @@ -1,4 +1,6 @@ pub mod balance; +pub mod get_shard; +pub mod get_shard_vault; pub mod nonce; pub mod set_balance; pub mod transfer; diff --git a/cli/src/trusted_base_cli/mod.rs b/cli/src/trusted_base_cli/mod.rs index 313c859d00..36c4c2019a 100644 --- a/cli/src/trusted_base_cli/mod.rs +++ b/cli/src/trusted_base_cli/mod.rs @@ -17,8 +17,9 @@ use crate::{ trusted_base_cli::commands::{ - balance::BalanceCommand, nonce::NonceCommand, set_balance::SetBalanceCommand, - transfer::TransferCommand, unshield_funds::UnshieldFundsCommand, + balance::BalanceCommand, get_shard::GetShardCommand, get_shard_vault::GetShardVaultCommand, + nonce::NonceCommand, set_balance::SetBalanceCommand, transfer::TransferCommand, + unshield_funds::UnshieldFundsCommand, }, trusted_cli::TrustedCli, trusted_command_utils::get_keystore_path, @@ -54,6 +55,12 @@ pub enum TrustedBaseCommand { /// gets the nonce of a given account, taking the pending trusted calls /// in top pool in consideration Nonce(NonceCommand), + + /// get shard for this worker + GetShard(GetShardCommand), + + /// get shard vault for shielding (if defined for this worker) + GetShardVault(GetShardVaultCommand), } impl TrustedBaseCommand { @@ -66,6 +73,8 @@ impl TrustedBaseCommand { TrustedBaseCommand::Balance(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::UnshieldFunds(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::Nonce(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::GetShard(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::GetShardVault(cmd) => cmd.run(cli, trusted_cli), } } } diff --git a/cli/src/trusted_cli.rs b/cli/src/trusted_cli.rs index 359fa05350..5c1f5d6553 100644 --- a/cli/src/trusted_cli.rs +++ b/cli/src/trusted_cli.rs @@ -25,7 +25,7 @@ use crate::trusted_base_cli::TrustedBaseCommand; pub struct TrustedCli { /// targeted worker MRENCLAVE #[clap(short, long)] - pub(crate) mrenclave: String, + pub(crate) mrenclave: Option, /// shard identifier #[clap(short, long)] diff --git a/cli/src/trusted_command_utils.rs b/cli/src/trusted_command_utils.rs index e01f2b9940..0041d1b9f9 100644 --- a/cli/src/trusted_command_utils.rs +++ b/cli/src/trusted_command_utils.rs @@ -91,7 +91,12 @@ pub(crate) fn get_keystore_path(trusted_args: &TrustedCli) -> PathBuf { } pub(crate) fn get_identifiers(trusted_args: &TrustedCli) -> ([u8; 32], ShardIdentifier) { - let mrenclave = mrenclave_from_base58(&trusted_args.mrenclave); + let mrenclave = mrenclave_from_base58( + trusted_args + .mrenclave + .as_ref() + .expect("argument '--mrenclave' must be provided for this command"), + ); let shard = match &trusted_args.shard { Some(val) => ShardIdentifier::from_slice(&val.from_base58().expect("shard has to be base58 encoded")), diff --git a/cli/src/trusted_operation.rs b/cli/src/trusted_operation.rs index 667083472c..2461d8b69d 100644 --- a/cli/src/trusted_operation.rs +++ b/cli/src/trusted_operation.rs @@ -222,7 +222,12 @@ pub fn read_shard(trusted_args: &TrustedCli) -> StdResult ShardIdentifier::decode(&mut &s[..]), _ => panic!("shard argument must be base58 encoded"), }, - None => match trusted_args.mrenclave.from_base58() { + None => match trusted_args + .mrenclave + .as_ref() + .expect("at least argument '--mrenclave' must be provided for this command") + .from_base58() + { Ok(s) => ShardIdentifier::decode(&mut &s[..]), _ => panic!("mrenclave argument must be base58 encoded"), }, diff --git a/core-primitives/stf-executor/src/enclave_signer.rs b/core-primitives/stf-executor/src/enclave_signer.rs index 6b41518d24..c6e2435339 100644 --- a/core-primitives/stf-executor/src/enclave_signer.rs +++ b/core-primitives/stf-executor/src/enclave_signer.rs @@ -17,7 +17,7 @@ use crate::{ error::{Error, Result}, - traits::StfEnclaveSigning, + traits::{StfEnclaveSigning, StfShardVaultQuery}, H256, }; use codec::{Decode, Encode}; @@ -25,7 +25,7 @@ use core::{fmt::Debug, marker::PhantomData}; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_sgx_crypto::{ed25519_derivation::DeriveEd25519, key_repository::AccessKey}; use itp_sgx_externalities::SgxExternalitiesTrait; -use itp_stf_interface::system_pallet::SystemPalletAccountInterface; +use itp_stf_interface::{system_pallet::SystemPalletAccountInterface, ShardVaultQuery}; use itp_stf_primitives::{ traits::TrustedCallSigning, types::{AccountId, KeyPair}, @@ -60,7 +60,8 @@ where StateObserver::StateType: SgxExternalitiesTrait, ShieldingKeyRepository: AccessKey, ::KeyType: DeriveEd25519, - Stf: SystemPalletAccountInterface, + Stf: SystemPalletAccountInterface + + ShardVaultQuery, Stf::Index: Into, TopPoolAuthor: AuthorApi + Send + Sync + 'static, TCS: PartialEq + Encode + Decode + Debug + Send + Sync, @@ -105,7 +106,8 @@ where StateObserver::StateType: SgxExternalitiesTrait, ShieldingKeyRepository: AccessKey, ::KeyType: DeriveEd25519, - Stf: SystemPalletAccountInterface, + Stf: SystemPalletAccountInterface + + ShardVaultQuery, Stf::Index: Into, TopPoolAuthor: AuthorApi + Send + Sync + 'static, TCS: PartialEq + Encode + Decode + Debug + Send + Sync, @@ -142,3 +144,25 @@ where )) } } + +impl StfShardVaultQuery + for StfEnclaveSigner +where + OCallApi: EnclaveAttestationOCallApi, + StateObserver: ObserveState, + StateObserver::StateType: SgxExternalitiesTrait, + ShieldingKeyRepository: AccessKey, + ::KeyType: DeriveEd25519, + Stf: SystemPalletAccountInterface + + ShardVaultQuery, + Stf::Index: Into, + TopPoolAuthor: AuthorApi + Send + Sync + 'static, + TCS: PartialEq + Encode + Decode + Debug + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + fn get_shard_vault(&self, shard: &ShardIdentifier) -> Result { + let vault = self.state_observer.observe_state(shard, move |state| Stf::get_vault(state))?; + + vault.ok_or_else(|| Error::Other("shard vault undefined".into())) + } +} diff --git a/core-primitives/stf-executor/src/mocks.rs b/core-primitives/stf-executor/src/mocks.rs index fd877f34e7..3539ca88a5 100644 --- a/core-primitives/stf-executor/src/mocks.rs +++ b/core-primitives/stf-executor/src/mocks.rs @@ -35,6 +35,7 @@ use sp_runtime::traits::Header as HeaderTrait; use std::sync::RwLock; use std::{boxed::Box, marker::PhantomData, ops::Deref, time::Duration, vec::Vec}; +use crate::traits::StfShardVaultQuery; use itp_stf_primitives::{ traits::{GetterAuthorization, TrustedCallVerification}, types::TrustedOperation, @@ -136,6 +137,12 @@ impl StfEnclaveSigning for StfEnclaveSigne } } +impl StfShardVaultQuery for StfEnclaveSignerMock { + fn get_shard_vault(&self, _shard: &ShardIdentifier) -> Result { + Err(crate::error::Error::Other("shard vault undefined".into())) + } +} + /// GetState mock #[derive(Default)] pub struct GetStateMock { diff --git a/core-primitives/stf-executor/src/traits.rs b/core-primitives/stf-executor/src/traits.rs index 5aed037b88..9f82b473b1 100644 --- a/core-primitives/stf-executor/src/traits.rs +++ b/core-primitives/stf-executor/src/traits.rs @@ -49,6 +49,10 @@ where ) -> Result; } +pub trait StfShardVaultQuery { + fn get_shard_vault(&self, shard: &ShardIdentifier) -> Result; +} + /// Proposes a state update to `Externalities`. pub trait StateUpdateProposer where diff --git a/core-primitives/stf-interface/src/lib.rs b/core-primitives/stf-interface/src/lib.rs index dd46c6c5ce..bdcf00238e 100644 --- a/core-primitives/stf-interface/src/lib.rs +++ b/core-primitives/stf-interface/src/lib.rs @@ -28,7 +28,10 @@ use core::fmt::Debug; use itp_node_api_metadata::NodeMetadataTrait; use itp_node_api_metadata_provider::AccessNodeMetadata; use itp_stf_primitives::traits::TrustedCallVerification; -use itp_types::{parentchain::ParentchainId, OpaqueCall}; +use itp_types::{ + parentchain::{AccountId, ParentchainId}, + OpaqueCall, +}; #[cfg(feature = "mocks")] pub mod mocks; @@ -44,6 +47,11 @@ pub trait InitState { fn init_state(enclave_account: AccountId) -> State; } +/// Interface to query shard vault account for shard +pub trait ShardVaultQuery { + fn get_vault(state: &mut S) -> Option; +} + /// Interface for all functions calls necessary to update an already /// initialized state. pub trait UpdateState { diff --git a/core-primitives/types/src/parentchain.rs b/core-primitives/types/src/parentchain.rs index 7bb9047cc4..80e2485ea5 100644 --- a/core-primitives/types/src/parentchain.rs +++ b/core-primitives/types/src/parentchain.rs @@ -129,6 +129,7 @@ where fn handle_events( executor: &Executor, events: impl FilterEvents, + vault_account: &AccountId, ) -> core::result::Result<(), Error>; } diff --git a/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs b/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs index 7554a617f2..0b8e6dbd30 100644 --- a/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs +++ b/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs @@ -22,7 +22,7 @@ use std::{boxed::Box, vec::Vec}; /// Block import dispatcher that immediately imports the blocks, without any processing or queueing. pub struct ImmediateDispatcher { - block_importer: BlockImporter, + pub block_importer: BlockImporter, import_event_observers: Vec>, } diff --git a/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs b/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs index 0d335db780..2438a07350 100644 --- a/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs +++ b/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs @@ -62,7 +62,7 @@ pub trait TriggerParentchainBlockImport { /// Dispatcher for block imports that retains blocks until the import is triggered, using the /// `TriggerParentchainBlockImport` trait implementation. pub struct TriggeredDispatcher { - block_importer: BlockImporter, + pub block_importer: BlockImporter, import_queue: BlockImportQueue, events_queue: EventsImportQueue, } diff --git a/core/parentchain/block-importer/src/block_importer.rs b/core/parentchain/block-importer/src/block_importer.rs index 008ed65b82..63e76e9210 100644 --- a/core/parentchain/block-importer/src/block_importer.rs +++ b/core/parentchain/block-importer/src/block_importer.rs @@ -47,7 +47,7 @@ pub struct ParentchainBlockImporter< validator_accessor: Arc, stf_executor: Arc, extrinsics_factory: Arc, - indirect_calls_executor: Arc, + pub indirect_calls_executor: Arc, _phantom: PhantomData, } @@ -144,7 +144,7 @@ impl< Ok(executed_shielding_calls) => { calls.push(executed_shielding_calls); }, - Err(_) => error!("[{:?}] Error executing relevant extrinsics", id), + Err(e) => error!("[{:?}] Error executing relevant extrinsics: {:?}", id, e), }; info!( diff --git a/core/parentchain/indirect-calls-executor/Cargo.toml b/core/parentchain/indirect-calls-executor/Cargo.toml index 37d49102c8..9f7356edeb 100644 --- a/core/parentchain/indirect-calls-executor/Cargo.toml +++ b/core/parentchain/indirect-calls-executor/Cargo.toml @@ -16,6 +16,7 @@ itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } itp-sgx-runtime-primitives = { path = "../../../core-primitives/sgx-runtime-primitives", default-features = false } itp-stf-executor = { path = "../../../core-primitives/stf-executor", default-features = false } +itp-stf-interface = { path = "../../../core-primitives/stf-interface", default-features = false } itp-stf-primitives = { path = "../../../core-primitives/stf-primitives", default-features = false } itp-test = { path = "../../../core-primitives/test", default-features = false } itp-top-pool-author = { path = "../../../core-primitives/top-pool-author", default-features = false } @@ -59,6 +60,7 @@ std = [ "itp-ocall-api/std", "itp-sgx-crypto/std", "itp-stf-executor/std", + "itp-stf-interface/std", "itp-top-pool-author/std", "itp-api-client-types/std", "itp-test/std", diff --git a/core/parentchain/indirect-calls-executor/src/executor.rs b/core/parentchain/indirect-calls-executor/src/executor.rs index 34946347ba..fc0b949f19 100644 --- a/core/parentchain/indirect-calls-executor/src/executor.rs +++ b/core/parentchain/indirect-calls-executor/src/executor.rs @@ -33,7 +33,7 @@ use itp_node_api::metadata::{ NodeMetadataTrait, }; use itp_sgx_crypto::{key_repository::AccessKey, ShieldingCryptoDecrypt, ShieldingCryptoEncrypt}; -use itp_stf_executor::traits::StfEnclaveSigning; +use itp_stf_executor::traits::{StfEnclaveSigning, StfShardVaultQuery}; use itp_stf_primitives::{ traits::{IndirectExecutor, TrustedCallSigning, TrustedCallVerification}, types::AccountId, @@ -60,7 +60,7 @@ pub struct IndirectCallsExecutor< G, > { pub(crate) shielding_key_repo: Arc, - pub(crate) stf_enclave_signer: Arc, + pub stf_enclave_signer: Arc, pub(crate) top_pool_author: Arc, pub(crate) node_meta_data_provider: Arc, _phantom: PhantomData<(IndirectCallsFilter, EventCreator, ParentchainEventHandler, TCS, G)>, @@ -129,7 +129,7 @@ impl< ShieldingKeyRepository: AccessKey, ::KeyType: ShieldingCryptoDecrypt + ShieldingCryptoEncrypt, - StfEnclaveSigner: StfEnclaveSigning, + StfEnclaveSigner: StfEnclaveSigning + StfShardVaultQuery, TopPoolAuthor: AuthorApi + Send + Sync + 'static, NodeMetadataProvider: AccessNodeMetadata, FilterIndirectCalls: FilterIntoDataFrom, @@ -166,7 +166,10 @@ impl< })?; trace!("xt_statuses:: {:?}", xt_statuses); - ParentchainEventHandler::handle_events(self, events)?; + let shard = self.get_default_shard(); + if let Ok(vault) = self.stf_enclave_signer.get_shard_vault(&shard) { + ParentchainEventHandler::handle_events(self, events, &vault)?; + } // This would be catastrophic but should never happen if xt_statuses.len() != block.extrinsics().len() { @@ -253,7 +256,7 @@ impl< ShieldingKeyRepository: AccessKey, ::KeyType: ShieldingCryptoDecrypt + ShieldingCryptoEncrypt, - StfEnclaveSigner: StfEnclaveSigning, + StfEnclaveSigner: StfEnclaveSigning + StfShardVaultQuery, TopPoolAuthor: AuthorApi + Send + Sync + 'static, TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, diff --git a/core/parentchain/indirect-calls-executor/src/mock.rs b/core/parentchain/indirect-calls-executor/src/mock.rs index a12a4b820c..bb7ad5a8db 100644 --- a/core/parentchain/indirect-calls-executor/src/mock.rs +++ b/core/parentchain/indirect-calls-executor/src/mock.rs @@ -187,6 +187,7 @@ where fn handle_events( _: &Executor, _: impl itp_types::parentchain::FilterEvents, + _: &AccountId, ) -> core::result::Result<(), Error> { Ok(()) } diff --git a/docker/README.md b/docker/README.md index 27f0a3990d..cac5c2b545 100644 --- a/docker/README.md +++ b/docker/README.md @@ -113,4 +113,4 @@ You can suppress the log output for a container by setting the logging driver. T logging: driver: local ``` -Mind the indent. Explanations for all the logging drivers in `docker compose` can be found [here](https://docs.docker.com/config/containers/logging/local/). \ No newline at end of file +Mind the indent. Explanations for all the logging drivers in `docker compose` can be found [here](https://docs.docker.com/config/containers/logging/local/). diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index 794b574e44..0bacf2606c 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -788,6 +788,7 @@ dependencies = [ "itc-direct-rpc-server", "itc-offchain-worker-executor", "itc-parentchain", + "itc-parentchain-block-import-dispatcher", "itc-parentchain-test", "itc-tls-websocket-server", "itp-attestation-handler", @@ -1856,6 +1857,7 @@ dependencies = [ "itp-sgx-crypto", "itp-sgx-runtime-primitives", "itp-stf-executor", + "itp-stf-interface", "itp-stf-primitives", "itp-test", "itp-top-pool-author", diff --git a/enclave-runtime/Cargo.toml b/enclave-runtime/Cargo.toml index 50a6b499b5..9de04c4ba5 100644 --- a/enclave-runtime/Cargo.toml +++ b/enclave-runtime/Cargo.toml @@ -99,6 +99,7 @@ ita-stf = { path = "../app-libs/stf", default-features = false, features = ["sgx itc-direct-rpc-server = { path = "../core/direct-rpc-server", default-features = false, features = ["sgx"] } itc-offchain-worker-executor = { path = "../core/offchain-worker-executor", default-features = false, features = ["sgx"] } itc-parentchain = { path = "../core/parentchain/parentchain-crate", default-features = false, features = ["sgx"] } +itc-parentchain-block-import-dispatcher = { path = "../core/parentchain/block-import-dispatcher", default-features = false, features = ["sgx"] } itc-parentchain-test = { path = "../core/parentchain/test", default-features = false } itc-tls-websocket-server = { path = "../core/tls-websocket-server", default-features = false, features = ["sgx"] } itp-attestation-handler = { path = "../core-primitives/attestation-handler", default-features = false, features = ["sgx"] } diff --git a/enclave-runtime/src/rpc/worker_api_direct.rs b/enclave-runtime/src/rpc/worker_api_direct.rs index 7ba57a1f52..019153a9d2 100644 --- a/enclave-runtime/src/rpc/worker_api_direct.rs +++ b/enclave-runtime/src/rpc/worker_api_direct.rs @@ -20,7 +20,10 @@ use crate::{ generate_dcap_ra_extrinsic_from_quote_internal, generate_ias_ra_extrinsic_from_der_cert_internal, }, - utils::get_validator_accessor_from_solo_or_parachain, + utils::{ + get_stf_enclave_signer_from_solo_or_parachain, + get_validator_accessor_from_solo_or_parachain, + }, }; use codec::Encode; use core::result::Result; @@ -30,7 +33,7 @@ use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, Extrinsi use itp_primitives_cache::{GetPrimitives, GLOBAL_PRIMITIVES_CACHE}; use itp_rpc::RpcReturnValue; use itp_sgx_crypto::key_repository::AccessPubkey; -use itp_stf_executor::getter_executor::ExecuteGetter; +use itp_stf_executor::{getter_executor::ExecuteGetter, traits::StfShardVaultQuery}; use itp_top_pool_author::traits::AuthorApi; use itp_types::{DirectRequestStatus, Request, ShardIdentifier, H256}; use itp_utils::{FromHexPrefixed, ToHexPrefixed}; @@ -40,6 +43,7 @@ use jsonrpc_core::{serde_json::json, IoHandler, Params, Value}; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_runtime::OpaqueExtrinsic; use std::{borrow::ToOwned, format, str, string::String, sync::Arc, vec::Vec}; + fn compute_hex_encoded_return_error(error_msg: &str) -> String { RpcReturnValue::from_error_message(error_msg).to_hex() } @@ -64,14 +68,12 @@ where GetterExecutor: ExecuteGetter + Send + Sync + 'static, AccessShieldingKey: AccessPubkey + Send + Sync + 'static, { - let io = IoHandler::new(); + let mut io = direct_top_pool_api::add_top_pool_direct_rpc_methods( + top_pool_author.clone(), + IoHandler::new(), + ); - // Add direct TOP pool rpc methods - let mut io = direct_top_pool_api::add_top_pool_direct_rpc_methods(top_pool_author, io); - - // author_getShieldingKey - let rsa_pubkey_name: &str = "author_getShieldingKey"; - io.add_sync_method(rsa_pubkey_name, move |_: Params| { + io.add_sync_method("author_getShieldingKey", move |_: Params| { let rsa_pubkey = match shielding_key.retrieve_pubkey() { Ok(key) => key, Err(status) => { @@ -93,8 +95,33 @@ where Ok(json!(json_value.to_hex())) }); - let mu_ra_url_name: &str = "author_getMuRaUrl"; - io.add_sync_method(mu_ra_url_name, move |_: Params| { + let local_top_pool_author = top_pool_author.clone(); + io.add_sync_method("author_getShardVault", move |_: Params| { + let shard = + local_top_pool_author.list_handled_shards().first().copied().unwrap_or_default(); + if let Ok(stf_enclave_signer) = get_stf_enclave_signer_from_solo_or_parachain() { + if let Ok(vault) = stf_enclave_signer.get_shard_vault(&shard) { + let json_value = + RpcReturnValue::new(vault.encode(), false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + } else { + Ok(json!(compute_hex_encoded_return_error("failed to get shard vault").to_hex())) + } + } else { + Ok(json!(compute_hex_encoded_return_error( + "failed to get stf_enclave_signer to get shard vault" + ) + .to_hex())) + } + }); + + io.add_sync_method("author_getShard", move |_: Params| { + let shard = top_pool_author.list_handled_shards().first().copied().unwrap_or_default(); + let json_value = RpcReturnValue::new(shard.encode(), false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + }); + + io.add_sync_method("author_getMuRaUrl", move |_: Params| { let url = match GLOBAL_PRIMITIVES_CACHE.get_mu_ra_url() { Ok(url) => url, Err(status) => { @@ -107,8 +134,7 @@ where Ok(json!(json_value.to_hex())) }); - let untrusted_url_name: &str = "author_getUntrustedUrl"; - io.add_sync_method(untrusted_url_name, move |_: Params| { + io.add_sync_method("author_getUntrustedUrl", move |_: Params| { let url = match GLOBAL_PRIMITIVES_CACHE.get_untrusted_worker_url() { Ok(url) => url, Err(status) => { @@ -121,31 +147,23 @@ where Ok(json!(json_value.to_hex())) }); - // chain_subscribeAllHeads - let chain_subscribe_all_heads_name: &str = "chain_subscribeAllHeads"; - io.add_sync_method(chain_subscribe_all_heads_name, |_: Params| { + io.add_sync_method("chain_subscribeAllHeads", |_: Params| { let parsed = "world"; Ok(Value::String(format!("hello, {}", parsed))) }); - // state_getMetadata - let state_get_metadata_name: &str = "state_getMetadata"; - io.add_sync_method(state_get_metadata_name, |_: Params| { + io.add_sync_method("state_getMetadata", |_: Params| { let metadata = Runtime::metadata(); let json_value = RpcReturnValue::new(metadata.into(), false, DirectRequestStatus::Ok); Ok(json!(json_value.to_hex())) }); - // state_getRuntimeVersion - let state_get_runtime_version_name: &str = "state_getRuntimeVersion"; - io.add_sync_method(state_get_runtime_version_name, |_: Params| { + io.add_sync_method("state_getRuntimeVersion", |_: Params| { let parsed = "world"; Ok(Value::String(format!("hello, {}", parsed))) }); - // state_executeGetter - let state_execute_getter_name: &str = "state_executeGetter"; - io.add_sync_method(state_execute_getter_name, move |params: Params| { + io.add_sync_method("state_executeGetter", move |params: Params| { let json_value = match execute_getter_inner(getter_executor.as_ref(), params) { Ok(state_getter_value) => RpcReturnValue { do_watch: false, @@ -158,9 +176,7 @@ where Ok(json!(json_value)) }); - // attesteer_forward_dcap_quote - let attesteer_forward_dcap_quote: &str = "attesteer_forwardDcapQuote"; - io.add_sync_method(attesteer_forward_dcap_quote, move |params: Params| { + io.add_sync_method("attesteer_forwardDcapQuote", move |params: Params| { let json_value = match forward_dcap_quote_inner(params) { Ok(val) => RpcReturnValue { do_watch: false, @@ -174,9 +190,7 @@ where Ok(json!(json_value)) }); - // attesteer_forward_ias_attestation_report - let attesteer_forward_ias_attestation_report: &str = "attesteer_forwardIasAttestationReport"; - io.add_sync_method(attesteer_forward_ias_attestation_report, move |params: Params| { + io.add_sync_method("attesteer_forwardIasAttestationReport", move |params: Params| { let json_value = match attesteer_forward_ias_attestation_report_inner(params) { Ok(val) => RpcReturnValue { do_watch: false, @@ -190,28 +204,21 @@ where Ok(json!(json_value)) }); - // system_health - let state_health_name: &str = "system_health"; - io.add_sync_method(state_health_name, |_: Params| { + io.add_sync_method("system_health", |_: Params| { let parsed = "world"; Ok(Value::String(format!("hello, {}", parsed))) }); - // system_name - let state_name_name: &str = "system_name"; - io.add_sync_method(state_name_name, |_: Params| { + io.add_sync_method("system_name", |_: Params| { let parsed = "world"; Ok(Value::String(format!("hello, {}", parsed))) }); - // system_version - let state_version_name: &str = "system_version"; - io.add_sync_method(state_version_name, |_: Params| { + io.add_sync_method("system_version", |_: Params| { let parsed = "world"; Ok(Value::String(format!("hello, {}", parsed))) }); - // returns all rpcs methods let rpc_methods_string = get_all_rpc_methods_string(&io); io.add_sync_method("rpc_methods", move |_: Params| { Ok(Value::String(rpc_methods_string.to_owned())) diff --git a/enclave-runtime/src/utils.rs b/enclave-runtime/src/utils.rs index 4c58da0d01..62c12ab93e 100644 --- a/enclave-runtime/src/utils.rs +++ b/enclave-runtime/src/utils.rs @@ -17,8 +17,8 @@ use crate::{ error::{Error, Result}, initialization::global_components::{ - EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveStfExecutor, - EnclaveValidatorAccessor, IntegriteeParentchainBlockImportDispatcher, + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveStfEnclaveSigner, + EnclaveStfExecutor, EnclaveValidatorAccessor, IntegriteeParentchainBlockImportDispatcher, IntegriteeParentchainTriggeredBlockImportDispatcher, GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, @@ -27,6 +27,7 @@ use crate::{ }, }; use codec::{Decode, Input}; +use itc_parentchain_block_import_dispatcher::BlockImportDispatcher; use itp_component_container::ComponentGetter; use std::{result::Result as StdResult, slice, sync::Arc}; @@ -171,3 +172,28 @@ pub(crate) fn get_stf_executor_from_solo_or_parachain() -> Result Result> +{ + let stf_enclave_signer = + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + match &*solochain_handler.import_dispatcher { + BlockImportDispatcher::TriggeredDispatcher(dispatcher) => + dispatcher.block_importer.indirect_calls_executor.stf_enclave_signer.clone(), + BlockImportDispatcher::ImmediateDispatcher(dispatcher) => + dispatcher.block_importer.indirect_calls_executor.stf_enclave_signer.clone(), + _ => return Err(Error::NoIntegriteeParentchainAssigned), + } + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + match &*parachain_handler.import_dispatcher { + BlockImportDispatcher::TriggeredDispatcher(dispatcher) => + dispatcher.block_importer.indirect_calls_executor.stf_enclave_signer.clone(), + BlockImportDispatcher::ImmediateDispatcher(dispatcher) => + dispatcher.block_importer.indirect_calls_executor.stf_enclave_signer.clone(), + _ => return Err(Error::NoIntegriteeParentchainAssigned), + } + } else { + return Err(Error::NoIntegriteeParentchainAssigned) + }; + Ok(stf_enclave_signer) +}