diff --git a/Cargo.lock b/Cargo.lock index e776371d44..e4919006bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2770,6 +2770,7 @@ dependencies = [ "itc-rest-client", "itc-rpc-client", "itc-rpc-server", + "itp-api-client-types", "itp-enclave-api", "itp-enclave-metrics", "itp-node-api", @@ -3034,7 +3035,7 @@ name = "itc-parentchain-block-import-dispatcher" version = "0.9.0" dependencies = [ "itc-parentchain-block-importer", - "itp-block-import-queue", + "itp-import-queue", "itp-types", "log 0.4.17", "sgx_tstd", @@ -3075,6 +3076,7 @@ dependencies = [ "futures 0.3.8", "ita-stf", "itc-parentchain-test", + "itp-api-client-types", "itp-node-api", "itp-ocall-api", "itp-sgx-crypto", @@ -3325,16 +3327,6 @@ dependencies = [ "yasna 0.3.1", ] -[[package]] -name = "itp-block-import-queue" -version = "0.8.0" -dependencies = [ - "sgx_tstd", - "sgx_types", - "thiserror 1.0.40", - "thiserror 1.0.9", -] - [[package]] name = "itp-component-container" version = "0.8.0" @@ -3408,6 +3400,16 @@ dependencies = [ "sp-core", ] +[[package]] +name = "itp-import-queue" +version = "0.8.0" +dependencies = [ + "sgx_tstd", + "sgx_types", + "thiserror 1.0.40", + "thiserror 1.0.9", +] + [[package]] name = "itp-networking-utils" version = "0.9.0" @@ -3895,8 +3897,8 @@ dependencies = [ "fork-tree", "itc-parentchain-light-client", "itc-parentchain-test", - "itp-block-import-queue", "itp-extrinsics-factory", + "itp-import-queue", "itp-node-api-metadata", "itp-node-api-metadata-provider", "itp-ocall-api", diff --git a/Cargo.toml b/Cargo.toml index 53d6953bd4..b0c1ac722a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ members = [ "core/rpc-server", "core/tls-websocket-server", "core-primitives/attestation-handler", - "core-primitives/block-import-queue", + "core-primitives/import-queue", "core-primitives/component-container", "core-primitives/enclave-api", "core-primitives/enclave-api/ffi", diff --git a/core-primitives/block-import-queue/Cargo.toml b/core-primitives/import-queue/Cargo.toml similarity index 96% rename from core-primitives/block-import-queue/Cargo.toml rename to core-primitives/import-queue/Cargo.toml index 20dd4119ec..23603d6631 100644 --- a/core-primitives/block-import-queue/Cargo.toml +++ b/core-primitives/import-queue/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "itp-block-import-queue" +name = "itp-import-queue" version = "0.8.0" authors = ["Integritee AG "] edition = "2021" diff --git a/core-primitives/block-import-queue/src/error.rs b/core-primitives/import-queue/src/error.rs similarity index 100% rename from core-primitives/block-import-queue/src/error.rs rename to core-primitives/import-queue/src/error.rs diff --git a/core-primitives/block-import-queue/src/block_import_queue.rs b/core-primitives/import-queue/src/import_queue.rs similarity index 70% rename from core-primitives/block-import-queue/src/block_import_queue.rs rename to core-primitives/import-queue/src/import_queue.rs index 3aa740b463..2555d3b5a3 100644 --- a/core-primitives/block-import-queue/src/block_import_queue.rs +++ b/core-primitives/import-queue/src/import_queue.rs @@ -15,7 +15,7 @@ */ -//! Block import queue implementation +//! Import queue implementation #[cfg(feature = "sgx")] use std::sync::SgxRwLock as RwLock; @@ -25,64 +25,64 @@ use std::sync::RwLock; use crate::{ error::{Error, Result}, - PeekBlockQueue, PopFromBlockQueue, PushToBlockQueue, + PeekQueue, PopFromQueue, PushToQueue, }; use std::{collections::VecDeque, vec::Vec}; -/// Block import queue. +/// Any import queue. /// /// Uses RwLock internally to guard against concurrent access and ensure all operations are atomic. -pub struct BlockImportQueue { - queue: RwLock>, +pub struct ImportQueue { + queue: RwLock>, } -impl BlockImportQueue { +impl ImportQueue { pub fn is_empty(&self) -> Result { let queue_lock = self.queue.read().map_err(|_| Error::PoisonedLock)?; Ok(queue_lock.is_empty()) } } -impl Default for BlockImportQueue { +impl Default for ImportQueue { fn default() -> Self { - BlockImportQueue { queue: Default::default() } + ImportQueue { queue: Default::default() } } } -impl PushToBlockQueue for BlockImportQueue { - fn push_multiple(&self, blocks: Vec) -> Result<()> { +impl PushToQueue for ImportQueue { + fn push_multiple(&self, items: Vec) -> Result<()> { let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; - queue_lock.extend(blocks); + queue_lock.extend(items); Ok(()) } - fn push_single(&self, block: SignedBlock) -> Result<()> { + fn push_single(&self, item: Item) -> Result<()> { let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; - queue_lock.push_back(block); + queue_lock.push_back(item); Ok(()) } } -impl PopFromBlockQueue for BlockImportQueue { - type BlockType = SignedBlock; +impl PopFromQueue for ImportQueue { + type ItemType = Item; - fn pop_all_but_last(&self) -> Result> { + fn pop_all_but_last(&self) -> Result> { let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; let queue_length = queue_lock.len(); if queue_length < 2 { - return Ok(Vec::::default()) + return Ok(Vec::::default()) } Ok(queue_lock.drain(..queue_length - 1).collect::>()) } - fn pop_all(&self) -> Result> { + fn pop_all(&self) -> Result> { let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; Ok(queue_lock.drain(..).collect::>()) } - fn pop_until(&self, predicate: Predicate) -> Result> + fn pop_until(&self, predicate: Predicate) -> Result> where - Predicate: FnMut(&Self::BlockType) -> bool, + Predicate: FnMut(&Self::ItemType) -> bool, { let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; match queue_lock.iter().position(predicate) { @@ -91,28 +91,38 @@ impl PopFromBlockQueue for BlockImportQueue { } } - fn pop_front(&self) -> Result> { + fn pop_front(&self) -> Result> { let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; Ok(queue_lock.pop_front()) } + + fn pop_from_front_until(&self, amount: usize) -> Result> { + let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; + if amount > queue_lock.len() { + return Err(Error::Other( + "Cannot Pop more items from the queue than are available".into(), + )) + } + Ok(queue_lock.drain(..amount).collect::>()) + } } -impl PeekBlockQueue for BlockImportQueue +impl PeekQueue for ImportQueue where - SignedBlock: Clone, + Item: Clone, { - type BlockType = SignedBlock; + type ItemType = Item; - fn peek_find(&self, predicate: Predicate) -> Result> + fn peek_find(&self, predicate: Predicate) -> Result> where - Predicate: Fn(&Self::BlockType) -> bool, + Predicate: Fn(&Self::ItemType) -> bool, { let queue_lock = self.queue.read().map_err(|_| Error::PoisonedLock)?; - let maybe_block = queue_lock.iter().find(|&b| predicate(b)); - Ok(maybe_block.cloned()) + let maybe_item = queue_lock.iter().find(|&b| predicate(b)); + Ok(maybe_item.cloned()) } - fn peek_last(&self) -> Result> { + fn peek_last(&self) -> Result> { let queue_lock = self.queue.read().map_err(|_| Error::PoisonedLock)?; Ok(queue_lock.back().cloned()) } @@ -132,26 +142,26 @@ mod tests { #[test] fn default_queue_is_empty() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); assert!(queue.is_empty().unwrap()); } #[test] fn pop_all_on_default_returns_empty_vec() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); assert!(queue.pop_all().unwrap().is_empty()); } #[test] fn after_inserting_queue_is_not_empty() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_single(TestBlock::default()).unwrap(); assert!(!queue.is_empty().unwrap()); } #[test] fn pop_all_after_inserting_leaves_empty_queue() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue .push_multiple(vec![TestBlock::default(), TestBlock::default(), TestBlock::default()]) .unwrap(); @@ -163,20 +173,20 @@ mod tests { #[test] fn pop_all_except_last_on_default_returns_empty_vec() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); assert!(queue.pop_all_but_last().unwrap().is_empty()); } #[test] fn pop_all_except_last_with_single_element_returns_empty_vec() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_single(TestBlock::default()).unwrap(); assert!(queue.pop_all_but_last().unwrap().is_empty()); } #[test] fn pop_all_except_last_with_multiple_elements_returns_all_but_last_inserted() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_multiple(vec![1, 3, 5, 7]).unwrap(); assert_eq!(3, queue.pop_all_but_last().unwrap().len()); assert!(!queue.is_empty().unwrap()); @@ -185,7 +195,7 @@ mod tests { #[test] fn pop_until_returns_empty_vec_if_nothing_matches() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_multiple(vec![1, 3, 5, 7]).unwrap(); let popped_elements = queue.pop_until(|i| i > &10u32).unwrap(); @@ -194,7 +204,7 @@ mod tests { #[test] fn pop_until_returns_elements_until_and_including_match() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_multiple(vec![1, 2, 3, 10]).unwrap(); assert_eq!(queue.pop_until(|i| i == &3).unwrap(), vec![1, 2, 3]); @@ -202,7 +212,7 @@ mod tests { #[test] fn pop_until_returns_all_elements_if_last_matches() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_multiple(vec![1, 2, 3, 10]).unwrap(); assert_eq!(queue.pop_until(|i| i == &10).unwrap(), vec![1, 2, 3, 10]); @@ -210,20 +220,20 @@ mod tests { #[test] fn pop_until_returns_first_element_if_it_matches() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_single(4).unwrap(); assert_eq!(queue.pop_until(|i| i == &4).unwrap(), vec![4]) } #[test] fn pop_front_returns_none_if_queue_is_empty() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); assert_matches!(queue.pop_front().unwrap(), None); } #[test] fn pop_front_works() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_multiple(vec![1, 2, 3, 5]).unwrap(); assert_eq!(queue.pop_front().unwrap(), Some(1)); assert_eq!(queue.pop_front().unwrap(), Some(2)); @@ -234,7 +244,7 @@ mod tests { #[test] fn peek_find_works() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_multiple(vec![1, 2, 3, 5]).unwrap(); assert_eq!(None, queue.peek_find(|i| i == &4).unwrap()); @@ -244,20 +254,20 @@ mod tests { #[test] fn peek_find_on_empty_queue_returns_none() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); assert_eq!(None, queue.peek_find(|i| i == &1).unwrap()); } #[test] fn peek_last_works() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); queue.push_multiple(vec![1, 2, 3, 5, 6, 9, 10]).unwrap(); assert_eq!(queue.peek_last().unwrap(), Some(10)); } #[test] fn peek_last_on_empty_queue_returns_none() { - let queue = BlockImportQueue::::default(); + let queue = ImportQueue::::default(); assert_eq!(None, queue.peek_last().unwrap()); } } diff --git a/core-primitives/block-import-queue/src/lib.rs b/core-primitives/import-queue/src/lib.rs similarity index 56% rename from core-primitives/block-import-queue/src/lib.rs rename to core-primitives/import-queue/src/lib.rs index bfbc022ad5..d223317f78 100644 --- a/core-primitives/block-import-queue/src/lib.rs +++ b/core-primitives/import-queue/src/lib.rs @@ -14,7 +14,7 @@ limitations under the License. */ -//! Queueing of block imports. +//! Queueing of item imports. #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(test, feature(assert_matches))] @@ -31,55 +31,58 @@ pub mod sgx_reexport_prelude { pub use thiserror_sgx as thiserror; } -pub mod block_import_queue; pub mod error; +pub mod import_queue; -pub use block_import_queue::*; +pub use import_queue::*; use error::Result; use std::vec::Vec; -/// Trait to push blocks to an import queue. -pub trait PushToBlockQueue { - /// Push multiple blocks to the queue, ordering from the Vec is preserved. - fn push_multiple(&self, blocks: Vec) -> Result<()>; +/// Trait to push items such as blocks to an import queue. +pub trait PushToQueue { + /// Push multiple items to the queue, ordering from the Vec is preserved. + fn push_multiple(&self, item: Vec) -> Result<()>; - /// Push a single block to the queue. - fn push_single(&self, block: BlockType) -> Result<()>; + /// Push a single item to the queue. + fn push_single(&self, item: Item) -> Result<()>; } -/// Trait to pop blocks from the import queue. -pub trait PopFromBlockQueue { - type BlockType; +/// Trait to pop items from the import queue. +pub trait PopFromQueue { + type ItemType; - /// Pop (i.e. removes and returns) all but the last block from the import queue. - fn pop_all_but_last(&self) -> Result>; + /// Pop (i.e. removes and returns) all but the last item from the import queue. + fn pop_all_but_last(&self) -> Result>; - /// Pop (i.e. removes and returns) all blocks from the import queue. - fn pop_all(&self) -> Result>; + /// Pop (i.e. removes and returns) all items from the import queue. + fn pop_all(&self) -> Result>; - /// Pop (front) until specified block is found. If no block matches, empty Vec is returned. - fn pop_until(&self, predicate: Predicate) -> Result> + /// Pop (front) until specified item is found. If no item matches, empty Vec is returned. + fn pop_until(&self, predicate: Predicate) -> Result> where - Predicate: Fn(&Self::BlockType) -> bool; + Predicate: Fn(&Self::ItemType) -> bool; /// Pop (front) queue. Returns None if queue is empty. - fn pop_front(&self) -> Result>; + fn pop_front(&self) -> Result>; + + /// Pop (front) queue until a specific amount of pops has been reached + fn pop_from_front_until(&self, amount: usize) -> Result>; } -/// Trait to peek blocks in the import queue without altering the queue. -pub trait PeekBlockQueue { - type BlockType: Clone; +/// Trait to peek items in the import queue without altering the queue. +pub trait PeekQueue { + type ItemType: Clone; /// Search the queue with a given predicate and return a reference to the first element that matches. /// Returns None if nothing matches. - fn peek_find(&self, predicate: Predicate) -> Result> + fn peek_find(&self, predicate: Predicate) -> Result> where - Predicate: Fn(&Self::BlockType) -> bool; + Predicate: Fn(&Self::ItemType) -> bool; /// Peeks the last element in the queue (aka the newest one, last to be popped). /// Returns None if queue is empty. - fn peek_last(&self) -> Result>; + fn peek_last(&self) -> Result>; /// Peek the queue size (i.e. number of elements the queue contains). fn peek_queue_size(&self) -> Result; diff --git a/core-primitives/node-api/api-client-extensions/src/chain.rs b/core-primitives/node-api/api-client-extensions/src/chain.rs index 11376adbe2..fa34ad0883 100644 --- a/core-primitives/node-api/api-client-extensions/src/chain.rs +++ b/core-primitives/node-api/api-client-extensions/src/chain.rs @@ -24,11 +24,11 @@ use itp_types::{ use sp_finality_grandpa::{AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY}; use sp_runtime::traits::GetRuntimeBlockType; use substrate_api_client::{ - rpc::Request, serde_impls::StorageKey, Api, ExtrinsicParams, FrameSystemConfig, GetBlock, - GetHeader, GetStorage, + rpc::Request, serde_impls::StorageKey, storage_key, Api, ExtrinsicParams, FrameSystemConfig, + GetBlock, GetHeader, GetStorage, }; -pub type Events = Vec; +type RawEvents = Vec; /// ApiClient extension that simplifies chain data access. pub trait ChainApi { @@ -44,7 +44,7 @@ pub trait ChainApi { fn grandpa_authorities(&self, hash: Option) -> ApiResult; fn grandpa_authorities_proof(&self, hash: Option) -> ApiResult; fn get_events_value_proof(&self, block_hash: Option) -> ApiResult; - fn get_events_for_block(&self, block_hash: Option) -> ApiResult; + fn get_events_for_block(&self, block_hash: Option) -> ApiResult; } impl ChainApi for Api @@ -109,13 +109,15 @@ where } fn get_events_value_proof(&self, block_hash: Option) -> ApiResult { + let key = storage_key("System", "Events"); Ok(self - .get_storage_value_proof("System", "Events", block_hash)? + .get_storage_proof_by_keys(Vec::from([key]), block_hash)? .map(|read_proof| read_proof.proof.into_iter().map(|bytes| bytes.0).collect()) .unwrap_or_default()) } - fn get_events_for_block(&self, block_hash: Option) -> ApiResult { - Ok(self.get_storage_value("System", "Events", block_hash)?.unwrap_or_default()) + fn get_events_for_block(&self, block_hash: Option) -> ApiResult { + let key = storage_key("System", "Events"); + Ok(self.get_opaque_storage_by_key_hash(key, block_hash)?.unwrap_or_default()) } } diff --git a/core-primitives/node-api/api-client-types/src/lib.rs b/core-primitives/node-api/api-client-types/src/lib.rs index 834514cac1..888108a0f1 100644 --- a/core-primitives/node-api/api-client-types/src/lib.rs +++ b/core-primitives/node-api/api-client-types/src/lib.rs @@ -26,9 +26,9 @@ pub use itp_types::parentchain::{ AccountId, Address, Balance, Hash, Index, Signature as PairSignature, }; pub use substrate_api_client::{ - storage_key, AssetTip, CallIndex, ExtrinsicParams, GenericAdditionalParams, - GenericExtrinsicParams, GenericSignedExtra, InvalidMetadataError, Metadata, MetadataError, - PlainTip, StaticExtrinsicSigner, UncheckedExtrinsicV4, + storage_key, AssetTip, CallIndex, EventDetails, Events, ExtrinsicParams, + GenericAdditionalParams, GenericExtrinsicParams, GenericSignedExtra, InvalidMetadataError, + Metadata, MetadataError, PlainTip, StaticEvent, StaticExtrinsicSigner, UncheckedExtrinsicV4, }; pub type ParentchainPlainTip = PlainTip; diff --git a/core-primitives/node-api/metadata/src/lib.rs b/core-primitives/node-api/metadata/src/lib.rs index f63c496c15..43c68a2964 100644 --- a/core-primitives/node-api/metadata/src/lib.rs +++ b/core-primitives/node-api/metadata/src/lib.rs @@ -23,14 +23,13 @@ use crate::{ error::Result, pallet_sidechain::SidechainCallIndexes, pallet_teerex::TeerexCallIndexes, }; use codec::{Decode, Encode}; -use itp_api_client_types::{Metadata, MetadataError}; use sp_core::storage::StorageKey; pub use crate::error::Error; +pub use itp_api_client_types::{Metadata, MetadataError}; pub mod error; pub mod pallet_sidechain; -pub mod pallet_system; pub mod pallet_teeracle; pub mod pallet_teerex; @@ -40,6 +39,14 @@ pub mod metadata_mocks; pub trait NodeMetadataTrait: TeerexCallIndexes + SidechainCallIndexes {} impl NodeMetadataTrait for T {} +impl TryFrom for Metadata { + type Error = crate::error::Error; + + fn try_from(value: NodeMetadata) -> core::result::Result { + value.node_metadata.ok_or(Error::MetadataNotSet) + } +} + #[derive(Default, Encode, Decode, Debug, Clone)] pub struct NodeMetadata { node_metadata: Option, diff --git a/core-primitives/node-api/metadata/src/metadata_mocks.rs b/core-primitives/node-api/metadata/src/metadata_mocks.rs index 0f451d0900..a3e288dad8 100644 --- a/core-primitives/node-api/metadata/src/metadata_mocks.rs +++ b/core-primitives/node-api/metadata/src/metadata_mocks.rs @@ -20,6 +20,16 @@ use crate::{ }; use codec::{Decode, Encode}; +use itp_api_client_types::Metadata; + +impl TryFrom for Metadata { + type Error = (); + + fn try_from(_: NodeMetadataMock) -> core::result::Result { + Err(()) + } +} + #[derive(Default, Encode, Decode, Debug, Clone)] pub struct NodeMetadataMock { teerex_module: u8, diff --git a/core-primitives/node-api/metadata/src/pallet_system.rs b/core-primitives/node-api/metadata/src/pallet_system.rs index 87efc8d8da..1a9b4c7958 100644 --- a/core-primitives/node-api/metadata/src/pallet_system.rs +++ b/core-primitives/node-api/metadata/src/pallet_system.rs @@ -1,18 +1,14 @@ /* - 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. - +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}; use sp_core::storage::StorageKey; @@ -21,17 +17,17 @@ use sp_core::storage::StorageKey; const SYSTEM: &str = "System"; pub trait SystemStorageIndexes { - fn system_account_storage_key(&self) -> Result; + fn system_account_storage_key(&self) -> Result; - fn system_account_storage_map_key(&self, index: u64) -> Result; + fn system_account_storage_map_key(&self, index: u64) -> Result; } impl SystemStorageIndexes for NodeMetadata { - fn system_account_storage_key(&self) -> Result { - self.storage_value_key(SYSTEM, "Account") - } - - fn system_account_storage_map_key(&self, index: u64) -> Result { - self.storage_map_key(SYSTEM, "Account", index) - } -} + fn system_account_storage_key(&self) -> Result { + self.storage_value_key(SYSTEM, "Account") + } + + fn system_account_storage_map_key(&self, index: u64) -> Result { + self.storage_map_key(SYSTEM, "Account", index) + } +} \ No newline at end of file diff --git a/core/parentchain/block-import-dispatcher/Cargo.toml b/core/parentchain/block-import-dispatcher/Cargo.toml index bbd54590e5..ad9d4acd47 100644 --- a/core/parentchain/block-import-dispatcher/Cargo.toml +++ b/core/parentchain/block-import-dispatcher/Cargo.toml @@ -11,7 +11,7 @@ sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-s # local dependencies itc-parentchain-block-importer = { path = "../block-importer", default-features = false } -itp-block-import-queue = { path = "../../../core-primitives/block-import-queue", default-features = false } +itp-import-queue = { path = "../../../core-primitives/import-queue", default-features = false } # sgx enabled external libraries thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } @@ -32,7 +32,7 @@ default = ["std"] std = [ # local "itc-parentchain-block-importer/std", - "itp-block-import-queue/std", + "itp-import-queue/std", # no-std compatible libraries "log/std", "sp-runtime/std", @@ -44,7 +44,7 @@ sgx = [ "sgx_tstd", # local "itc-parentchain-block-importer/sgx", - "itp-block-import-queue/sgx", + "itp-import-queue/sgx", # sgx enabled external libraries "thiserror_sgx", ] diff --git a/core/parentchain/block-import-dispatcher/src/error.rs b/core/parentchain/block-import-dispatcher/src/error.rs index bc75fd97c2..b5d73ffe54 100644 --- a/core/parentchain/block-import-dispatcher/src/error.rs +++ b/core/parentchain/block-import-dispatcher/src/error.rs @@ -33,7 +33,7 @@ pub enum Error { #[error("Even though there is no dispatcher assigned, the dispatch function is called.")] NoDispatcherAssigned, #[error("Block import queue error: {0}")] - BlockImportQueue(#[from] itp_block_import_queue::error::Error), + ImportQueue(#[from] itp_import_queue::error::Error), #[error("Block import error: {0}")] BlockImport(#[from] itc_parentchain_block_importer::error::Error), #[error(transparent)] diff --git a/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs b/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs index c639ddeafa..7554a617f2 100644 --- a/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs +++ b/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs @@ -47,9 +47,9 @@ impl DispatchBlockImport where BlockImporter: ImportParentchainBlocks, { - fn dispatch_import(&self, blocks: Vec) -> Result<()> { + fn dispatch_import(&self, blocks: Vec, events: Vec>) -> Result<()> { debug!("Importing {} parentchain blocks", blocks.len()); - self.block_importer.import_parentchain_blocks(blocks)?; + self.block_importer.import_parentchain_blocks(blocks, events)?; debug!("Notifying {} observers of import", self.import_event_observers.len()); self.import_event_observers.iter().for_each(|callback| callback()); Ok(()) @@ -93,7 +93,7 @@ mod tests { counter_clone.increment(); }); - dispatcher.dispatch_import(vec![1u32, 2u32]).unwrap(); + dispatcher.dispatch_import(vec![1u32, 2u32], vec![]).unwrap(); assert_eq!(1, notification_counter.get_counter()); } diff --git a/core/parentchain/block-import-dispatcher/src/lib.rs b/core/parentchain/block-import-dispatcher/src/lib.rs index 758c456a95..7cb9831647 100644 --- a/core/parentchain/block-import-dispatcher/src/lib.rs +++ b/core/parentchain/block-import-dispatcher/src/lib.rs @@ -46,7 +46,7 @@ pub trait DispatchBlockImport { /// Dispatch blocks to be imported. /// /// The blocks may be imported immediately, get queued, delayed or grouped. - fn dispatch_import(&self, blocks: Vec) -> Result<()>; + fn dispatch_import(&self, blocks: Vec, events: Vec>) -> Result<()>; } /// Wrapper for the actual dispatchers. Allows to define one global type for @@ -99,13 +99,20 @@ where TriggeredDispatcher: DispatchBlockImport, ImmediateDispatcher: DispatchBlockImport, { - fn dispatch_import(&self, blocks: Vec) -> Result<()> { + fn dispatch_import(&self, blocks: Vec, events: Vec>) -> Result<()> { match self { - BlockImportDispatcher::TriggeredDispatcher(dispatcher) => - dispatcher.dispatch_import(blocks), - BlockImportDispatcher::ImmediateDispatcher(dispatcher) => - dispatcher.dispatch_import(blocks), - BlockImportDispatcher::EmptyDispatcher => Err(Error::NoDispatcherAssigned), + BlockImportDispatcher::TriggeredDispatcher(dispatcher) => { + log::info!("TRIGGERED DISPATCHER MATCH"); + dispatcher.dispatch_import(blocks, events) + }, + BlockImportDispatcher::ImmediateDispatcher(dispatcher) => { + log::info!("IMMEDIATE DISPATCHER MATCH"); + dispatcher.dispatch_import(blocks, events) + }, + BlockImportDispatcher::EmptyDispatcher => { + log::info!("EMPTY DISPATCHER DISPATCHER MATCH"); + Err(Error::NoDispatcherAssigned) + }, } } } diff --git a/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs b/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs index b5c824fac2..0d335db780 100644 --- a/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs +++ b/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs @@ -22,10 +22,12 @@ use crate::{ DispatchBlockImport, }; use itc_parentchain_block_importer::ImportParentchainBlocks; -use itp_block_import_queue::{PeekBlockQueue, PopFromBlockQueue, PushToBlockQueue}; -use log::debug; +use itp_import_queue::{PeekQueue, PopFromQueue, PushToQueue}; +use log::trace; use std::vec::Vec; +pub type RawEventsPerBlock = Vec; + /// Trait to specifically trigger the import of parentchain blocks. pub trait TriggerParentchainBlockImport { type SignedBlockType; @@ -59,71 +61,101 @@ pub trait TriggerParentchainBlockImport { /// Dispatcher for block imports that retains blocks until the import is triggered, using the /// `TriggerParentchainBlockImport` trait implementation. -pub struct TriggeredDispatcher { +pub struct TriggeredDispatcher { block_importer: BlockImporter, import_queue: BlockImportQueue, + events_queue: EventsImportQueue, } -impl TriggeredDispatcher +impl + TriggeredDispatcher where BlockImporter: ImportParentchainBlocks, - BlockImportQueue: PushToBlockQueue - + PopFromBlockQueue, + BlockImportQueue: PushToQueue + + PopFromQueue, + EventsImportQueue: PushToQueue + PopFromQueue, { - pub fn new(block_importer: BlockImporter, block_import_queue: BlockImportQueue) -> Self { - TriggeredDispatcher { block_importer, import_queue: block_import_queue } + pub fn new( + block_importer: BlockImporter, + block_import_queue: BlockImportQueue, + events_import_queue: EventsImportQueue, + ) -> Self { + TriggeredDispatcher { + block_importer, + import_queue: block_import_queue, + events_queue: events_import_queue, + } } } -impl DispatchBlockImport - for TriggeredDispatcher +impl + DispatchBlockImport + for TriggeredDispatcher where BlockImporter: ImportParentchainBlocks, - BlockImportQueue: - PushToBlockQueue + PopFromBlockQueue, + BlockImportQueue: PushToQueue + PopFromQueue, + EventsImportQueue: PushToQueue + PopFromQueue, { - fn dispatch_import(&self, blocks: Vec) -> Result<()> { - debug!("Pushing parentchain block(s) ({}) to import queue", blocks.len()); + fn dispatch_import( + &self, + blocks: Vec, + events: Vec, + ) -> Result<()> { + trace!( + "Pushing parentchain block(s) and event(s) ({}) ({}) to import queue", + blocks.len(), + events.len() + ); // Push all the blocks to be dispatched into the queue. - self.import_queue.push_multiple(blocks).map_err(Error::BlockImportQueue) + self.events_queue.push_multiple(events).map_err(Error::ImportQueue)?; + self.import_queue.push_multiple(blocks).map_err(Error::ImportQueue) } } -impl TriggerParentchainBlockImport - for TriggeredDispatcher +impl TriggerParentchainBlockImport + for TriggeredDispatcher where BlockImporter: ImportParentchainBlocks, - BlockImportQueue: PushToBlockQueue - + PopFromBlockQueue - + PeekBlockQueue, + BlockImportQueue: PushToQueue + + PopFromQueue + + PeekQueue, + EventsImportQueue: PushToQueue + + PopFromQueue + + PeekQueue, { type SignedBlockType = BlockImporter::SignedBlockType; fn import_all(&self) -> Result> { - let blocks_to_import = self.import_queue.pop_all().map_err(Error::BlockImportQueue)?; + let blocks_to_import = self.import_queue.pop_all().map_err(Error::ImportQueue)?; + let events_to_import = self.events_queue.pop_all().map_err(Error::ImportQueue)?; let latest_imported_block = blocks_to_import.last().map(|b| (*b).clone()); - debug!("Trigger import of all parentchain blocks in queue ({})", blocks_to_import.len()); + trace!( + "Trigger import of all parentchain blocks and events in queue ({}) ({})", + blocks_to_import.len(), + events_to_import.len() + ); self.block_importer - .import_parentchain_blocks(blocks_to_import) + .import_parentchain_blocks(blocks_to_import, events_to_import) .map_err(Error::BlockImport)?; Ok(latest_imported_block) } fn import_all_but_latest(&self) -> Result<()> { - let blocks_to_import = - self.import_queue.pop_all_but_last().map_err(Error::BlockImportQueue)?; + let blocks_to_import = self.import_queue.pop_all_but_last().map_err(Error::ImportQueue)?; + let events_to_import = self.events_queue.pop_all_but_last().map_err(Error::ImportQueue)?; - debug!( - "Trigger import of all parentchain blocks, except the latest, from queue ({})", - blocks_to_import.len() + trace!( + "Trigger import of all parentchain blocks and events, except the latest, from queue ({}) ({})", + blocks_to_import.len(), + events_to_import.len() ); self.block_importer - .import_parentchain_blocks(blocks_to_import) + .import_parentchain_blocks(blocks_to_import, events_to_import) .map_err(Error::BlockImport) } @@ -132,17 +164,23 @@ where predicate: impl Fn(&BlockImporter::SignedBlockType) -> bool, ) -> Result> { let blocks_to_import = - self.import_queue.pop_until(predicate).map_err(Error::BlockImportQueue)?; + self.import_queue.pop_until(predicate).map_err(Error::ImportQueue)?; + + let events_to_import = self + .events_queue + .pop_from_front_until(blocks_to_import.len()) + .map_err(Error::ImportQueue)?; let latest_imported_block = blocks_to_import.last().map(|b| (*b).clone()); - debug!( - "Import of parentchain blocks has been triggered, importing {} blocks from queue", - blocks_to_import.len() + trace!( + "Import of parentchain blocks and events has been triggered, importing {} blocks and {} events from queue", + blocks_to_import.len(), + events_to_import.len(), ); self.block_importer - .import_parentchain_blocks(blocks_to_import) + .import_parentchain_blocks(blocks_to_import, events_to_import) .map_err(Error::BlockImport)?; Ok(latest_imported_block) @@ -152,19 +190,19 @@ where &self, predicate: impl Fn(&BlockImporter::SignedBlockType) -> bool, ) -> Result> { - debug!( + trace!( "Peek find parentchain import queue (currently has {} elements)", self.import_queue.peek_queue_size().unwrap_or(0) ); - self.import_queue.peek_find(predicate).map_err(Error::BlockImportQueue) + self.import_queue.peek_find(predicate).map_err(Error::ImportQueue) } fn peek_latest(&self) -> Result> { - debug!( + trace!( "Peek latest parentchain import queue (currently has {} elements)", self.import_queue.peek_queue_size().unwrap_or(0) ); - self.import_queue.peek_last().map_err(Error::BlockImportQueue) + self.import_queue.peek_last().map_err(Error::ImportQueue) } } @@ -172,39 +210,54 @@ where mod tests { use super::*; use itc_parentchain_block_importer::block_importer_mock::ParentchainBlockImporterMock; - use itp_block_import_queue::{BlockImportQueue, PopFromBlockQueue}; + use itp_import_queue::{ImportQueue, PopFromQueue}; type SignedBlockType = u32; type TestBlockImporter = ParentchainBlockImporterMock; - type TestQueue = BlockImportQueue; - type TestDispatcher = TriggeredDispatcher; + type TestQueue = ImportQueue; + type TestEventsQueue = ImportQueue; + type TestDispatcher = TriggeredDispatcher; #[test] fn dispatching_blocks_imports_none_if_not_triggered() { let dispatcher = test_fixtures(); - dispatcher.dispatch_import(vec![1, 2, 3, 4, 5]).unwrap(); + dispatcher + .dispatch_import(vec![1, 2, 3, 4, 5], vec![vec![1], vec![2], vec![3], vec![4], vec![5]]) + .unwrap(); assert!(dispatcher.block_importer.get_all_imported_blocks().is_empty()); assert_eq!(dispatcher.import_queue.pop_all().unwrap(), vec![1, 2, 3, 4, 5]); + assert_eq!( + dispatcher.events_queue.pop_all().unwrap(), + vec![vec![1], vec![2], vec![3], vec![4], vec![5]] + ); } #[test] fn dispatching_blocks_multiple_times_add_all_to_queue() { let dispatcher = test_fixtures(); - dispatcher.dispatch_import(vec![1, 2, 3, 4, 5]).unwrap(); - dispatcher.dispatch_import(vec![6, 7, 8]).unwrap(); + dispatcher + .dispatch_import(vec![1, 2, 3, 4, 5], vec![vec![1], vec![2], vec![3], vec![4], vec![5]]) + .unwrap(); + dispatcher + .dispatch_import(vec![6, 7, 8], vec![vec![6], vec![7], vec![8]]) + .unwrap(); assert!(dispatcher.block_importer.get_all_imported_blocks().is_empty()); assert_eq!(dispatcher.import_queue.pop_all().unwrap(), vec![1, 2, 3, 4, 5, 6, 7, 8]); + assert_eq!( + dispatcher.events_queue.pop_all().unwrap(), + vec![vec![1], vec![2], vec![3], vec![4], vec![5], vec![6], vec![7], vec![8]] + ); } #[test] fn triggering_import_all_empties_queue() { let dispatcher = test_fixtures(); - dispatcher.dispatch_import(vec![1, 2, 3, 4, 5]).unwrap(); + dispatcher.dispatch_import(vec![1, 2, 3, 4, 5], vec![]).unwrap(); let latest_imported = dispatcher.import_all().unwrap().unwrap(); assert_eq!(latest_imported, 5); @@ -216,7 +269,7 @@ mod tests { fn triggering_import_all_on_empty_queue_imports_none() { let dispatcher = test_fixtures(); - dispatcher.dispatch_import(vec![]).unwrap(); + dispatcher.dispatch_import(vec![], vec![]).unwrap(); let maybe_latest_imported = dispatcher.import_all().unwrap(); assert!(maybe_latest_imported.is_none()); @@ -225,38 +278,48 @@ mod tests { Vec::::default() ); assert!(dispatcher.import_queue.is_empty().unwrap()); + assert!(dispatcher.events_queue.is_empty().unwrap()); } #[test] fn triggering_import_until_leaves_remaining_in_queue() { let dispatcher = test_fixtures(); - dispatcher.dispatch_import(vec![1, 2, 3, 4, 5]).unwrap(); + dispatcher + .dispatch_import(vec![1, 2, 3, 4, 5], vec![vec![1], vec![2], vec![3], vec![4], vec![5]]) + .unwrap(); let latest_imported = dispatcher.import_until(|i: &SignedBlockType| i == &4).unwrap().unwrap(); assert_eq!(latest_imported, 4); assert_eq!(dispatcher.block_importer.get_all_imported_blocks(), vec![1, 2, 3, 4]); assert_eq!(dispatcher.import_queue.pop_all().unwrap(), vec![5]); + assert_eq!(dispatcher.events_queue.pop_all().unwrap(), vec![vec![5]]); } #[test] fn triggering_import_until_with_no_match_imports_nothing() { let dispatcher = test_fixtures(); - dispatcher.dispatch_import(vec![1, 2, 3, 4, 5]).unwrap(); + dispatcher + .dispatch_import(vec![1, 2, 3, 4, 5], vec![vec![1], vec![2], vec![3], vec![4], vec![5]]) + .unwrap(); let maybe_latest_imported = dispatcher.import_until(|i: &SignedBlockType| i == &8).unwrap(); assert!(maybe_latest_imported.is_none()); assert!(dispatcher.block_importer.get_all_imported_blocks().is_empty()); assert_eq!(dispatcher.import_queue.pop_all().unwrap(), vec![1, 2, 3, 4, 5]); + assert_eq!( + dispatcher.events_queue.pop_all().unwrap(), + vec![vec![1], vec![2], vec![3], vec![4], vec![5]] + ); } #[test] fn trigger_import_all_but_latest_works() { let dispatcher = test_fixtures(); - dispatcher.dispatch_import(vec![1, 2, 3, 4, 5]).unwrap(); + dispatcher.dispatch_import(vec![1, 2, 3, 4, 5], vec![]).unwrap(); dispatcher.import_all_but_latest().unwrap(); assert_eq!(dispatcher.block_importer.get_all_imported_blocks(), vec![1, 2, 3, 4]); @@ -264,9 +327,11 @@ mod tests { } fn test_fixtures() -> TestDispatcher { - let import_queue = BlockImportQueue::::default(); + let events_import_queue = ImportQueue::::default(); + let import_queue = ImportQueue::::default(); let block_importer = ParentchainBlockImporterMock::::default(); - let dispatcher = TriggeredDispatcher::new(block_importer, import_queue); + let dispatcher = + TriggeredDispatcher::new(block_importer, import_queue, events_import_queue); dispatcher } } diff --git a/core/parentchain/block-importer/src/block_importer.rs b/core/parentchain/block-importer/src/block_importer.rs index 7ebf313058..0074ee3af5 100644 --- a/core/parentchain/block-importer/src/block_importer.rs +++ b/core/parentchain/block-importer/src/block_importer.rs @@ -118,11 +118,14 @@ impl< fn import_parentchain_blocks( &self, blocks_to_import: Vec, + events_to_import: Vec>, ) -> Result<()> { let mut calls = Vec::::new(); debug!("Import blocks to light-client!"); - for signed_block in blocks_to_import.into_iter() { + for (signed_block, raw_events) in + blocks_to_import.into_iter().zip(events_to_import.into_iter()) + { // Check if there are any extrinsics in the to-be-imported block that we sent and cached in the light-client before. // If so, remove them now from the cache. if let Err(e) = self.validator_accessor.execute_mut_on_validator(|v| { @@ -143,7 +146,10 @@ impl< // Execute indirect calls that were found in the extrinsics of the block, // incl. shielding and unshielding. - match self.indirect_calls_executor.execute_indirect_calls_in_extrinsics(&block) { + match self + .indirect_calls_executor + .execute_indirect_calls_in_extrinsics(&block, &raw_events) + { Ok(executed_shielding_calls) => { calls.push(executed_shielding_calls); }, diff --git a/core/parentchain/block-importer/src/block_importer_mock.rs b/core/parentchain/block-importer/src/block_importer_mock.rs index 912c3409b4..5308ef4e71 100644 --- a/core/parentchain/block-importer/src/block_importer_mock.rs +++ b/core/parentchain/block-importer/src/block_importer_mock.rs @@ -50,6 +50,7 @@ where fn import_parentchain_blocks( &self, blocks_to_import: Vec, + _events: Vec>, ) -> Result<()> { let mut imported_blocks_lock = self.imported_blocks.write().map_err(|e| { Error::Other(format!("failed to acquire lock for imported blocks vec: {:?}", e).into()) diff --git a/core/parentchain/block-importer/src/lib.rs b/core/parentchain/block-importer/src/lib.rs index f22b60546f..98ecb2e6a0 100644 --- a/core/parentchain/block-importer/src/lib.rs +++ b/core/parentchain/block-importer/src/lib.rs @@ -50,6 +50,9 @@ pub trait ImportParentchainBlocks { /// * Validates and execute those extrinsics, mutating state /// * Includes block headers into the light client /// * Sends `PROCESSED_PARENTCHAIN_BLOCK` extrinsics that include the merkle root of all processed calls - fn import_parentchain_blocks(&self, blocks_to_import: Vec) - -> Result<()>; + fn import_parentchain_blocks( + &self, + blocks_to_import: Vec, + events_to_import: Vec>, + ) -> Result<()>; } diff --git a/core/parentchain/indirect-calls-executor/Cargo.toml b/core/parentchain/indirect-calls-executor/Cargo.toml index c91a908b5e..9bccb58df5 100644 --- a/core/parentchain/indirect-calls-executor/Cargo.toml +++ b/core/parentchain/indirect-calls-executor/Cargo.toml @@ -11,6 +11,7 @@ sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-s # local dependencies ita-stf = { path = "../../../app-libs/stf", default-features = false } +itp-api-client-types = { path = "../../../core-primitives/node-api/api-client-types", default-features = false } itp-node-api = { path = "../../../core-primitives/node-api", default-features = false } itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } @@ -58,6 +59,7 @@ std = [ "itp-sgx-crypto/std", "itp-stf-executor/std", "itp-top-pool-author/std", + "itp-api-client-types/std", "itp-types/std", "log/std", #substrate diff --git a/core/parentchain/indirect-calls-executor/src/event_filter.rs b/core/parentchain/indirect-calls-executor/src/event_filter.rs new file mode 100644 index 0000000000..971443f904 --- /dev/null +++ b/core/parentchain/indirect-calls-executor/src/event_filter.rs @@ -0,0 +1,79 @@ +/* + 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. + +*/ +//! Various way to filter Parentchain events + +use crate::error::Result; +use codec::{Decode, Encode}; +use itp_api_client_types::{Events, StaticEvent}; +use itp_types::H256; +use std::vec::Vec; + +#[derive(Encode, Decode, Debug)] +pub struct ExtrinsicSuccess; + +impl StaticEvent for ExtrinsicSuccess { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "ExtrinsicSuccess"; +} + +#[derive(Encode, Decode)] +pub struct ExtrinsicFailed; + +impl StaticEvent for ExtrinsicFailed { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "ExtrinsicFailed"; +} + +#[derive(Debug)] +pub enum ExtrinsicStatus { + Success, + Failed, +} +pub trait FilterEvents { + fn get_extrinsic_statuses(&self) -> Result>; +} + +impl FilterEvents for Events { + fn get_extrinsic_statuses(&self) -> Result> { + Ok(self + .iter() + .filter_map(|ev| { + ev.and_then(|ev| { + if (ev.as_event::()?).is_some() { + return Ok(Some(ExtrinsicStatus::Success)) + } + + if (ev.as_event::()?).is_some() { + return Ok(Some(ExtrinsicStatus::Failed)) + } + + Ok(None) + }) + .ok() + .flatten() + }) + .collect()) + } +} + +pub struct MockEvents; + +impl FilterEvents for MockEvents { + fn get_extrinsic_statuses(&self) -> Result> { + Ok(Vec::from([ExtrinsicStatus::Success])) + } +} diff --git a/core/parentchain/indirect-calls-executor/src/executor.rs b/core/parentchain/indirect-calls-executor/src/executor.rs index 91a95367d8..d426468f00 100644 --- a/core/parentchain/indirect-calls-executor/src/executor.rs +++ b/core/parentchain/indirect-calls-executor/src/executor.rs @@ -20,8 +20,9 @@ use crate::sgx_reexport_prelude::*; use crate::{ - error::Result, - filter_calls::FilterCalls, + error::{Error, Result}, + event_filter::{ExtrinsicStatus, FilterEvents}, + filter_metadata::{EventsFromMetadata, FilterIntoDataFrom}, traits::{ExecuteIndirectCalls, IndirectDispatch, IndirectExecutor}, }; use binary_merkle_tree::merkle_root; @@ -39,7 +40,7 @@ use itp_types::{OpaqueCall, ShardIdentifier, H256}; use log::*; use sp_core::blake2_256; use sp_runtime::traits::{Block as ParentchainBlockTrait, Header, Keccak256}; -use std::{sync::Arc, vec::Vec}; +use std::{fmt::Debug, sync::Arc, vec::Vec}; pub struct IndirectCallsExecutor< ShieldingKeyRepository, @@ -47,12 +48,13 @@ pub struct IndirectCallsExecutor< TopPoolAuthor, NodeMetadataProvider, IndirectCallsFilter, + EventCreator, > { pub(crate) shielding_key_repo: Arc, pub(crate) stf_enclave_signer: Arc, pub(crate) top_pool_author: Arc, pub(crate) node_meta_data_provider: Arc, - _phantom: PhantomData, + _phantom: PhantomData<(IndirectCallsFilter, EventCreator)>, } impl< ShieldingKeyRepository, @@ -60,6 +62,7 @@ impl< TopPoolAuthor, NodeMetadataProvider, IndirectCallsFilter, + EventCreator, > IndirectCallsExecutor< ShieldingKeyRepository, @@ -67,6 +70,7 @@ impl< TopPoolAuthor, NodeMetadataProvider, IndirectCallsFilter, + EventCreator, > { pub fn new( @@ -91,6 +95,7 @@ impl< TopPoolAuthor, NodeMetadataProvider, FilterIndirectCalls, + EventCreator, > ExecuteIndirectCalls for IndirectCallsExecutor< ShieldingKeyRepository, @@ -98,6 +103,7 @@ impl< TopPoolAuthor, NodeMetadataProvider, FilterIndirectCalls, + EventCreator, > where ShieldingKeyRepository: AccessKey, ::KeyType: ShieldingCryptoDecrypt @@ -105,13 +111,15 @@ impl< StfEnclaveSigner: StfEnclaveSigning, TopPoolAuthor: AuthorApi + Send + Sync + 'static, NodeMetadataProvider: AccessNodeMetadata, - NodeMetadataProvider::MetadataType: NodeMetadataTrait, - FilterIndirectCalls: FilterCalls, - FilterIndirectCalls::Call: IndirectDispatch + Encode, + FilterIndirectCalls: FilterIntoDataFrom, + NodeMetadataProvider::MetadataType: NodeMetadataTrait + Clone, + FilterIndirectCalls::Output: IndirectDispatch + Encode + Debug, + EventCreator: EventsFromMetadata, { fn execute_indirect_calls_in_extrinsics( &self, block: &ParentchainBlock, + events: &[u8], ) -> Result where ParentchainBlock: ParentchainBlockTrait, @@ -122,11 +130,26 @@ impl< debug!("Scanning block {:?} for relevant xt", block_number); let mut executed_calls = Vec::::new(); - for xt_opaque in block.extrinsics().iter() { + let events = self + .node_meta_data_provider + .get_from_metadata(|metadata| { + EventCreator::create_from_metadata(metadata.clone(), block_hash, events) + })? + .ok_or_else(|| Error::Other("Could not create events from metadata".into()))?; + + let xt_statuses = events.get_extrinsic_statuses()?; + debug!("xt_statuses:: {:?}", xt_statuses); + + // This would be catastrophic but should never happen + if xt_statuses.len() != block.extrinsics().len() { + return Err(Error::Other("Extrinsic Status and Extrinsic count not equal".into())) + } + + for (xt_opaque, xt_status) in block.extrinsics().iter().zip(xt_statuses.iter()) { let encoded_xt_opaque = xt_opaque.encode(); let maybe_call = self.node_meta_data_provider.get_from_metadata(|metadata| { - FilterIndirectCalls::filter_into_with_metadata(&encoded_xt_opaque, metadata) + FilterIndirectCalls::filter_into_from_metadata(&encoded_xt_opaque, metadata) })?; let call = match maybe_call { @@ -134,12 +157,16 @@ impl< None => continue, }; - if let Err(e) = call.dispatch(self) { - log::warn!("Error executing the indirect call: {:?}", e); + if let ExtrinsicStatus::Failed = xt_status { + warn!("Parentchain Extrinsic Failed, {:?} wont be dispatched", call); continue - }; + } - executed_calls.push(hash_of(&call)) + if let Err(e) = call.dispatch(self) { + warn!("Error executing the indirect call: {:?}. Error {:?}", call, e); + } else { + executed_calls.push(hash_of(&call)); + } } // Include a processed parentchain block confirmation for each block. @@ -174,6 +201,7 @@ impl< TopPoolAuthor, NodeMetadataProvider, FilterIndirectCalls, + EventFilter, > IndirectExecutor for IndirectCallsExecutor< ShieldingKeyRepository, @@ -181,6 +209,7 @@ impl< TopPoolAuthor, NodeMetadataProvider, FilterIndirectCalls, + EventFilter, > where ShieldingKeyRepository: AccessKey, ::KeyType: ShieldingCryptoDecrypt @@ -227,8 +256,8 @@ pub(crate) fn hash_of(xt: &T) -> H256 { mod test { use super::*; use crate::{ - filter_calls::ShieldFundsAndCallWorkerFilter, - parentchain_extrinsic_parser::ParentchainExtrinsicParser, + filter_metadata::{ShieldFundsAndCallWorkerFilter, TestEventCreator}, + parentchain_parser::ParentchainExtrinsicParser, }; use codec::{Decode, Encode}; use ita_stf::TrustedOperation; @@ -262,6 +291,7 @@ mod test { TestTopPoolAuthor, TestNodeMetadataRepository, ShieldFundsAndCallWorkerFilter, + TestEventCreator, >; type Seed = [u8; 32]; @@ -283,7 +313,7 @@ mod test { .build(); indirect_calls_executor - .execute_indirect_calls_in_extrinsics(&parentchain_block) + .execute_indirect_calls_in_extrinsics(&parentchain_block, &Vec::new()) .unwrap(); assert_eq!(1, top_pool_author.pending_tops(shard_id()).unwrap().len()); @@ -308,7 +338,7 @@ mod test { .build(); indirect_calls_executor - .execute_indirect_calls_in_extrinsics(&parentchain_block) + .execute_indirect_calls_in_extrinsics(&parentchain_block, &Vec::new()) .unwrap(); assert_eq!(1, top_pool_author.pending_tops(shard_id()).unwrap().len()); diff --git a/core/parentchain/indirect-calls-executor/src/filter_calls.rs b/core/parentchain/indirect-calls-executor/src/filter_metadata.rs similarity index 58% rename from core/parentchain/indirect-calls-executor/src/filter_calls.rs rename to core/parentchain/indirect-calls-executor/src/filter_metadata.rs index a3590d4dd3..23d87bde8f 100644 --- a/core/parentchain/indirect-calls-executor/src/filter_calls.rs +++ b/core/parentchain/indirect-calls-executor/src/filter_metadata.rs @@ -17,35 +17,80 @@ use crate::{ error::Result, + event_filter::{FilterEvents, MockEvents}, indirect_calls::{CallWorkerArgs, ShiedFundsArgs}, - parentchain_extrinsic_parser::ParseExtrinsic, + parentchain_parser::ParseExtrinsic, IndirectDispatch, IndirectExecutor, }; use codec::{Decode, Encode}; use core::marker::PhantomData; +use itp_api_client_types::{Events, Metadata}; use itp_node_api::metadata::{NodeMetadata, NodeMetadataTrait}; +use itp_types::H256; -/// Trait to filter an indirect call and decode into it, where the decoding -/// is based on the metadata provided. -pub trait FilterCalls { - /// Call enum we try to decode into. - type Call; +pub trait EventsFromMetadata { + type Output: FilterEvents; + + fn create_from_metadata( + metadata: NodeMetadata, + block_hash: H256, + events: &[u8], + ) -> Option; +} - /// Knows how to parse the parentchain extrinsics. - type ParseParentchainExtrinsic; +pub struct EventCreator; + +impl + Clone> EventsFromMetadata for EventCreator { + type Output = Events; + + fn create_from_metadata( + metadata: NodeMetadata, + block_hash: H256, + events: &[u8], + ) -> Option { + let raw_metadata: Metadata = metadata.try_into().ok()?; + Some(Events::::new(raw_metadata, block_hash, events.to_vec())) + } +} - /// Filters some bytes and returns `Some(Self::Call)` if the filter matches some criteria. - fn filter_into_with_metadata(call: &[u8], metadata: &NodeMetadata) -> Option; +pub struct TestEventCreator; + +impl EventsFromMetadata for TestEventCreator { + type Output = MockEvents; + + fn create_from_metadata( + _metadata: NodeMetadata, + _block_hash: H256, + _events: &[u8], + ) -> Option { + Some(MockEvents) + } +} + +/// Trait to filter an indirect call and decode into it, where the decoding +/// is based on the metadata provided. +pub trait FilterIntoDataFrom { + /// Type to decode into. + type Output; + + /// Knows how to parse the parentchain metadata. + type ParseParentchainMetadata; + + /// Filters some bytes and returns `Some(Self::Output)` if the filter matches some criteria. + fn filter_into_from_metadata( + encoded_data: &[u8], + metadata: &NodeMetadata, + ) -> Option; } /// Indirect calls filter denying all indirect calls. pub struct DenyAll; -impl FilterCalls for DenyAll { - type Call = (); - type ParseParentchainExtrinsic = (); +impl FilterIntoDataFrom for DenyAll { + type Output = (); + type ParseParentchainMetadata = (); - fn filter_into_with_metadata(_: &[u8], _: &NodeMetadata) -> Option { + fn filter_into_from_metadata(_: &[u8], _: &NodeMetadata) -> Option { None } } @@ -55,20 +100,23 @@ pub struct ShieldFundsAndCallWorkerFilter { _phantom: PhantomData, } -impl FilterCalls +impl FilterIntoDataFrom for ShieldFundsAndCallWorkerFilter where ExtrinsicParser: ParseExtrinsic, { - type Call = IndirectCall; - type ParseParentchainExtrinsic = ExtrinsicParser; + type Output = IndirectCall; + type ParseParentchainMetadata = ExtrinsicParser; - fn filter_into_with_metadata(call: &[u8], metadata: &NodeMetadata) -> Option { - let call_mut = &mut &call[..]; + fn filter_into_from_metadata( + encoded_data: &[u8], + metadata: &NodeMetadata, + ) -> Option { + let call_mut = &mut &encoded_data[..]; // Todo: the filter should not need to parse, only filter. This should directly be configured // in the indirect executor. - let xt = match Self::ParseParentchainExtrinsic::parse(call_mut) { + let xt = match Self::ParseParentchainMetadata::parse(call_mut) { Ok(xt) => xt, Err(e) => { log::error!("Could not parse parentchain extrinsic: {:?}", e); diff --git a/core/parentchain/indirect-calls-executor/src/lib.rs b/core/parentchain/indirect-calls-executor/src/lib.rs index 7eda490819..bd7935a898 100644 --- a/core/parentchain/indirect-calls-executor/src/lib.rs +++ b/core/parentchain/indirect-calls-executor/src/lib.rs @@ -37,13 +37,14 @@ pub mod sgx_reexport_prelude { pub use thiserror_sgx as thiserror; } +mod event_filter; mod executor; mod traits; pub mod error; -pub mod filter_calls; +pub mod filter_metadata; pub mod indirect_calls; -pub mod parentchain_extrinsic_parser; +pub mod parentchain_parser; pub use error::{Error, Result}; pub use executor::IndirectCallsExecutor; diff --git a/core/parentchain/indirect-calls-executor/src/parentchain_extrinsic_parser.rs b/core/parentchain/indirect-calls-executor/src/parentchain_parser.rs similarity index 100% rename from core/parentchain/indirect-calls-executor/src/parentchain_extrinsic_parser.rs rename to core/parentchain/indirect-calls-executor/src/parentchain_parser.rs diff --git a/core/parentchain/indirect-calls-executor/src/traits.rs b/core/parentchain/indirect-calls-executor/src/traits.rs index f06387a903..3cc0efcf34 100644 --- a/core/parentchain/indirect-calls-executor/src/traits.rs +++ b/core/parentchain/indirect-calls-executor/src/traits.rs @@ -30,6 +30,7 @@ pub trait ExecuteIndirectCalls { fn execute_indirect_calls_in_extrinsics( &self, block: &ParentchainBlock, + events: &[u8], ) -> Result where ParentchainBlock: ParentchainBlockTrait; diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index e0b665f47f..2dd17ab8ad 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -687,10 +687,10 @@ dependencies = [ "itc-parentchain-test", "itc-tls-websocket-server", "itp-attestation-handler", - "itp-block-import-queue", "itp-component-container", "itp-extrinsics-factory", "itp-hashing", + "itp-import-queue", "itp-node-api", "itp-node-api-metadata", "itp-nonce-cache", @@ -1644,7 +1644,7 @@ name = "itc-parentchain-block-import-dispatcher" version = "0.9.0" dependencies = [ "itc-parentchain-block-importer", - "itp-block-import-queue", + "itp-import-queue", "log", "sgx_tstd", "sgx_types", @@ -1679,6 +1679,7 @@ dependencies = [ "bs58", "futures 0.3.8", "ita-stf", + "itp-api-client-types", "itp-node-api", "itp-ocall-api", "itp-sgx-crypto", @@ -1845,15 +1846,6 @@ dependencies = [ "yasna", ] -[[package]] -name = "itp-block-import-queue" -version = "0.8.0" -dependencies = [ - "sgx_tstd", - "sgx_types", - "thiserror 1.0.9", -] - [[package]] name = "itp-component-container" version = "0.8.0" @@ -1895,6 +1887,15 @@ dependencies = [ "sp-core", ] +[[package]] +name = "itp-import-queue" +version = "0.8.0" +dependencies = [ + "sgx_tstd", + "sgx_types", + "thiserror 1.0.9", +] + [[package]] name = "itp-node-api" version = "0.9.0" @@ -2329,8 +2330,8 @@ version = "0.9.0" dependencies = [ "fork-tree", "itc-parentchain-light-client", - "itp-block-import-queue", "itp-extrinsics-factory", + "itp-import-queue", "itp-node-api-metadata", "itp-node-api-metadata-provider", "itp-ocall-api", diff --git a/enclave-runtime/Cargo.toml b/enclave-runtime/Cargo.toml index f0e229c0e4..944af0673a 100644 --- a/enclave-runtime/Cargo.toml +++ b/enclave-runtime/Cargo.toml @@ -96,10 +96,10 @@ itc-parentchain = { path = "../core/parentchain/parentchain-crate", default-feat 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"] } -itp-block-import-queue = { path = "../core-primitives/block-import-queue", default-features = false, features = ["sgx"] } itp-component-container = { path = "../core-primitives/component-container", default-features = false, features = ["sgx"] } itp-extrinsics-factory = { path = "../core-primitives/extrinsics-factory", default-features = false, features = ["sgx"] } itp-hashing = { path = "../core-primitives/hashing", default-features = false } +itp-import-queue = { path = "../core-primitives/import-queue", default-features = false, features = ["sgx"] } itp-node-api = { path = "../core-primitives/node-api", default-features = false, features = ["sgx"] } itp-node-api-metadata = { path = "../core-primitives/node-api/metadata", default-features = false } itp-nonce-cache = { path = "../core-primitives/nonce-cache", default-features = false, features = ["sgx"] } diff --git a/enclave-runtime/src/error.rs b/enclave-runtime/src/error.rs index 5f0fa0571b..4c7ac4de6f 100644 --- a/enclave-runtime/src/error.rs +++ b/enclave-runtime/src/error.rs @@ -41,6 +41,8 @@ pub enum Error { ExpectedTriggeredImportDispatcher, CouldNotDispatchBlockImport, NoParentchainAssigned, + ParentChainValidation(itp_storage::error::Error), + ParentChainSync, PrimitivesAccess(itp_primitives_cache::error::Error), MutexAccess, Attestation(itp_attestation_handler::error::Error), diff --git a/enclave-runtime/src/initialization/global_components.rs b/enclave-runtime/src/initialization/global_components.rs index 9b2b73be4b..544aee95a6 100644 --- a/enclave-runtime/src/initialization/global_components.rs +++ b/enclave-runtime/src/initialization/global_components.rs @@ -41,8 +41,9 @@ use itc_parentchain::{ }, block_importer::ParentchainBlockImporter, indirect_calls_executor::{ - filter_calls::ShieldFundsAndCallWorkerFilter, - parentchain_extrinsic_parser::ParentchainExtrinsicParser, IndirectCallsExecutor, + filter_metadata::{EventCreator, ShieldFundsAndCallWorkerFilter}, + parentchain_parser::ParentchainExtrinsicParser, + IndirectCallsExecutor, }, light_client::{ concurrent_access::ValidatorAccessor, io::LightClientStateSeal, @@ -53,9 +54,9 @@ use itc_tls_websocket_server::{ config_provider::FromFileConfigProvider, ws_server::TungsteniteWsServer, ConnectionToken, }; use itp_attestation_handler::IntelAttestationHandler; -use itp_block_import_queue::BlockImportQueue; use itp_component_container::ComponentContainer; use itp_extrinsics_factory::ExtrinsicsFactory; +use itp_import_queue::ImportQueue; use itp_node_api::{ api_client::PairSignature, metadata::{provider::NodeMetadataRepository, NodeMetadata}, @@ -88,6 +89,7 @@ use its_sidechain::{ consensus_common::{BlockImportConfirmationHandler, BlockImportQueueWorker, PeerBlockSync}, }; use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; +use sgx_tstd::vec::Vec; use sp_core::ed25519::Pair; pub type EnclaveParentchainSigner = @@ -137,6 +139,7 @@ pub type EnclaveIndirectCallsExecutor = IndirectCallsExecutor< EnclaveTopPoolAuthor, EnclaveNodeMetadataRepository, ShieldFundsAndCallWorkerFilter, + EventCreator, >; pub type EnclaveValidatorAccessor = ValidatorAccessor< LightValidation, @@ -150,9 +153,14 @@ pub type EnclaveParentchainBlockImporter = ParentchainBlockImporter< EnclaveExtrinsicsFactory, EnclaveIndirectCallsExecutor, >; -pub type EnclaveParentchainBlockImportQueue = BlockImportQueue; -pub type EnclaveTriggeredParentchainBlockImportDispatcher = - TriggeredDispatcher; +pub type EnclaveParentchainBlockImportQueue = ImportQueue; +// Should not be a Vec> +pub type EnclaveParentchainEventImportQueue = ImportQueue>; +pub type EnclaveTriggeredParentchainBlockImportDispatcher = TriggeredDispatcher< + EnclaveParentchainBlockImporter, + EnclaveParentchainBlockImportQueue, + EnclaveParentchainEventImportQueue, +>; pub type EnclaveImmediateParentchainBlockImportDispatcher = ImmediateDispatcher; @@ -184,7 +192,7 @@ pub type EnclaveSidechainBlockImporter = SidechainBlockImporter< EnclaveTopPoolAuthor, EnclaveTriggeredParentchainBlockImportDispatcher, >; -pub type EnclaveSidechainBlockImportQueue = BlockImportQueue; +pub type EnclaveSidechainBlockImportQueue = ImportQueue; pub type EnclaveBlockImportConfirmationHandler = BlockImportConfirmationHandler< ParentchainBlock, <::Block as SidechainBlockTrait>::HeaderType, diff --git a/enclave-runtime/src/initialization/parentchain/common.rs b/enclave-runtime/src/initialization/parentchain/common.rs index c0cf521657..d3c0c20182 100644 --- a/enclave-runtime/src/initialization/parentchain/common.rs +++ b/enclave-runtime/src/initialization/parentchain/common.rs @@ -23,7 +23,7 @@ use crate::{ EnclaveIndirectCallsExecutor, EnclaveNodeMetadataRepository, EnclaveOffchainWorkerExecutor, EnclaveParentchainBlockImportDispatcher, EnclaveParentchainBlockImportQueue, EnclaveParentchainBlockImporter, - EnclaveParentchainSigner, EnclaveStfExecutor, + EnclaveParentchainEventImportQueue, EnclaveParentchainSigner, EnclaveStfExecutor, EnclaveTriggeredParentchainBlockImportDispatcher, EnclaveValidatorAccessor, GLOBAL_OCALL_API_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_STATE_OBSERVER_COMPONENT, @@ -119,9 +119,11 @@ pub(crate) fn create_sidechain_triggered_import_dispatcher( block_importer: EnclaveParentchainBlockImporter, ) -> Arc { let parentchain_block_import_queue = EnclaveParentchainBlockImportQueue::default(); + let parentchain_event_import_queue = EnclaveParentchainEventImportQueue::default(); let triggered_dispatcher = EnclaveTriggeredParentchainBlockImportDispatcher::new( block_importer, parentchain_block_import_queue, + parentchain_event_import_queue, ); Arc::new(EnclaveParentchainBlockImportDispatcher::new_triggered_dispatcher(Arc::new( triggered_dispatcher, diff --git a/enclave-runtime/src/lib.rs b/enclave-runtime/src/lib.rs index dbb83f5adb..91eee070bc 100644 --- a/enclave-runtime/src/lib.rs +++ b/enclave-runtime/src/lib.rs @@ -45,19 +45,20 @@ use codec::{alloc::string::String, Decode}; use itc_parentchain::block_import_dispatcher::{ triggered_dispatcher::TriggerParentchainBlockImport, DispatchBlockImport, }; -use itp_block_import_queue::PushToBlockQueue; use itp_component_container::ComponentGetter; +use itp_import_queue::PushToQueue; use itp_node_api::metadata::NodeMetadata; use itp_nonce_cache::{MutateNonce, Nonce, GLOBAL_NONCE_CACHE}; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; use itp_sgx_crypto::{ed25519, Ed25519Seal, Rsa3072Seal}; use itp_sgx_io::StaticSealedIO; -use itp_storage::StorageProof; +use itp_storage::{StorageProof, StorageProofChecker}; use itp_types::{ShardIdentifier, SignedBlock}; use itp_utils::write_slice_and_whitespace_pad; use log::*; use sgx_types::sgx_status_t; use sp_core::crypto::Pair; +use sp_runtime::traits::BlakeTwo256; use std::{boxed::Box, slice, vec::Vec}; mod attestation; @@ -339,8 +340,8 @@ pub unsafe extern "C" fn init_shard(shard: *const u8, shard_size: u32) -> sgx_st pub unsafe extern "C" fn sync_parentchain( blocks_to_sync: *const u8, blocks_to_sync_size: usize, - _events_to_sync: *const u8, - _events_to_sync_size: *const u8, + events_to_sync: *const u8, + events_to_sync_size: usize, events_proofs_to_sync: *const u8, events_proofs_to_sync_size: usize, _nonce: *const u32, @@ -363,9 +364,14 @@ pub unsafe extern "C" fn sync_parentchain( return e.into() } - // TODO: Need to pass validated events down this path or store them somewhere such that - // the `indirect_calls_executor` can access them to verify extrinsics in each block have succeeded or not. - if let Err(e) = dispatch_parentchain_blocks_for_import::(blocks_to_sync) { + let events_to_sync = match Vec::>::decode_raw(events_to_sync, events_to_sync_size) { + Ok(events) => events, + Err(e) => return Error::Codec(e).into(), + }; + + if let Err(e) = + dispatch_parentchain_blocks_for_import::(blocks_to_sync, events_to_sync) + { return e.into() } @@ -382,6 +388,7 @@ pub unsafe extern "C" fn sync_parentchain( /// fn dispatch_parentchain_blocks_for_import( blocks_to_sync: Vec, + events_to_sync: Vec>, ) -> Result<()> { if WorkerModeProvider::worker_mode() == WorkerMode::Teeracle { trace!("Not importing any parentchain blocks"); @@ -397,11 +404,10 @@ fn dispatch_parentchain_blocks_for_import return Err(Error::NoParentchainAssigned) }; - import_dispatcher.dispatch_import(blocks_to_sync)?; + import_dispatcher.dispatch_import(blocks_to_sync, events_to_sync)?; Ok(()) } -// ANDREW /// Validates the events coming from the parentchain fn validate_events( events_proofs: &Vec, @@ -412,6 +418,30 @@ fn validate_events( events_proofs.len(), blocks_merkle_roots.len() ); + + if events_proofs.len() != blocks_merkle_roots.len() { + return Err(Error::ParentChainSync) + } + + let events_key = itp_storage::storage_value_key("System", "Events"); + + let validated_events: Result>> = events_proofs + .iter() + .zip(blocks_merkle_roots.iter()) + .map(|(proof, root)| { + StorageProofChecker::::check_proof( + *root, + events_key.as_slice(), + proof.clone(), + ) + .ok() + .flatten() + .ok_or_else(|| Error::ParentChainValidation(itp_storage::Error::WrongValue)) + }) + .collect(); + + let _ = validated_events?; + Ok(()) } diff --git a/enclave-runtime/src/test/top_pool_tests.rs b/enclave-runtime/src/test/top_pool_tests.rs index a49514bd8c..b4e0ba6447 100644 --- a/enclave-runtime/src/test/top_pool_tests.rs +++ b/enclave-runtime/src/test/top_pool_tests.rs @@ -34,9 +34,9 @@ use ita_stf::{ TrustedCall, TrustedOperation, }; use itc_parentchain::indirect_calls_executor::{ - filter_calls::ShieldFundsAndCallWorkerFilter, - parentchain_extrinsic_parser::ParentchainExtrinsicParser, ExecuteIndirectCalls, - IndirectCallsExecutor, + filter_metadata::{ShieldFundsAndCallWorkerFilter, TestEventCreator}, + parentchain_parser::ParentchainExtrinsicParser, + ExecuteIndirectCalls, IndirectCallsExecutor, }; use itc_parentchain_test::{ParentchainBlockBuilder, ParentchainHeaderBuilder}; use itp_node_api::{ @@ -135,6 +135,7 @@ pub fn submit_shielding_call_to_top_pool() { _, _, ShieldFundsAndCallWorkerFilter, + TestEventCreator, >::new( shielding_key_repo, enclave_signer, top_pool_author.clone(), node_meta_data_repository ); @@ -142,7 +143,7 @@ pub fn submit_shielding_call_to_top_pool() { let block_with_shielding_call = create_shielding_call_extrinsic(shard_id, &shielding_key); let _ = indirect_calls_executor - .execute_indirect_calls_in_extrinsics(&block_with_shielding_call) + .execute_indirect_calls_in_extrinsics(&block_with_shielding_call, &Vec::new()) .unwrap(); assert_eq!(1, top_pool_author.get_pending_trusted_calls(shard_id).len()); diff --git a/service/Cargo.toml b/service/Cargo.toml index 1eb564c6be..34f9a92ce3 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -44,6 +44,7 @@ itc-parentchain = { path = "../core/parentchain/parentchain-crate" } itc-rest-client = { path = "../core/rest-client" } itc-rpc-client = { path = "../core/rpc-client" } itc-rpc-server = { path = "../core/rpc-server" } +itp-api-client-types = { path = "../core-primitives/node-api/api-client-types" } itp-enclave-api = { path = "../core-primitives/enclave-api" } itp-enclave-metrics = { path = "../core-primitives/enclave-metrics" } itp-node-api = { path = "../core-primitives/node-api" } diff --git a/service/src/parentchain_handler.rs b/service/src/parentchain_handler.rs index 62aafb0bde..a37e24387c 100644 --- a/service/src/parentchain_handler.rs +++ b/service/src/parentchain_handler.rs @@ -148,6 +148,8 @@ where }) .collect::, _>>()?; + println!("[+] Found {} event vector(s) to sync", events_chunk_to_sync.len()); + let events_proofs_chunk_to_sync: Vec = block_chunk_to_sync .iter() .map(|block| { diff --git a/service/src/tests/mocks/parentchain_api_mock.rs b/service/src/tests/mocks/parentchain_api_mock.rs index 2aafbbc95f..9277b4891d 100644 --- a/service/src/tests/mocks/parentchain_api_mock.rs +++ b/service/src/tests/mocks/parentchain_api_mock.rs @@ -89,10 +89,7 @@ impl ChainApi for ParentchainApiMock { Ok(Default::default()) } - fn get_events_for_block( - &self, - _block_hash: Option, - ) -> ApiResult { + fn get_events_for_block(&self, _block_hash: Option) -> ApiResult> { Ok(Default::default()) } } diff --git a/sidechain/consensus/common/Cargo.toml b/sidechain/consensus/common/Cargo.toml index dc8fbba752..45d5e71b57 100644 --- a/sidechain/consensus/common/Cargo.toml +++ b/sidechain/consensus/common/Cargo.toml @@ -12,8 +12,8 @@ thiserror = { version = "1.0.26", optional = true } # local deps fork-tree = { path = "../../fork-tree", default-features = false } itc-parentchain-light-client = { path = "../../../core/parentchain/light-client", default-features = false } -itp-block-import-queue = { path = "../../../core-primitives/block-import-queue", default-features = false } itp-extrinsics-factory = { path = "../../../core-primitives/extrinsics-factory", default-features = false } +itp-import-queue = { path = "../../../core-primitives/import-queue", default-features = false } itp-node-api-metadata = { path = "../../../core-primitives/node-api/metadata", default-features = false } itp-node-api-metadata-provider = { path = "../../../core-primitives/node-api/metadata-provider", default-features = false } itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } @@ -50,7 +50,7 @@ std = [ "thiserror", # local "itc-parentchain-light-client/std", - "itp-block-import-queue/std", + "itp-import-queue/std", "itp-extrinsics-factory/std", "itp-node-api-metadata/std", "itp-node-api-metadata-provider/std", @@ -72,7 +72,7 @@ sgx = [ "thiserror-sgx", # local "itc-parentchain-light-client/sgx", - "itp-block-import-queue/sgx", + "itp-import-queue/sgx", "itp-extrinsics-factory/sgx", "itp-node-api-metadata-provider/sgx", "itp-sgx-crypto/sgx", diff --git a/sidechain/consensus/common/src/block_import_queue_worker.rs b/sidechain/consensus/common/src/block_import_queue_worker.rs index 3687c5df3d..fc7d9a23ef 100644 --- a/sidechain/consensus/common/src/block_import_queue_worker.rs +++ b/sidechain/consensus/common/src/block_import_queue_worker.rs @@ -17,7 +17,7 @@ use crate::{Error, Result, SyncBlockFromPeer}; use core::marker::PhantomData; -use itp_block_import_queue::PopFromBlockQueue; +use itp_import_queue::PopFromQueue; use its_primitives::traits::{Block as BlockTrait, SignedBlock as SignedSidechainBlockTrait}; use log::debug; use sp_runtime::traits::Block as ParentchainBlockTrait; @@ -49,7 +49,7 @@ where ParentchainBlock: ParentchainBlockTrait, SignedSidechainBlock: SignedSidechainBlockTrait, SignedSidechainBlock::Block: BlockTrait, - BlockImportQueue: PopFromBlockQueue, + BlockImportQueue: PopFromQueue, PeerBlockSyncer: SyncBlockFromPeer, { pub fn new( @@ -85,7 +85,7 @@ impl ParentchainBlock: ParentchainBlockTrait, SignedSidechainBlock: SignedSidechainBlockTrait, SignedSidechainBlock::Block: BlockTrait, - BlockImportQueue: PopFromBlockQueue, + BlockImportQueue: PopFromQueue, PeerBlockSyncer: SyncBlockFromPeer, { fn process_queue( diff --git a/sidechain/consensus/common/src/error.rs b/sidechain/consensus/common/src/error.rs index 1f1b1f21f8..e272f942f3 100644 --- a/sidechain/consensus/common/src/error.rs +++ b/sidechain/consensus/common/src/error.rs @@ -63,7 +63,7 @@ pub enum Error { #[error("Could not import block (number: {0}). A block with this number is already imported (current state block number: {1})")] BlockAlreadyImported(BlockNumber, BlockNumber), #[error("Failed to pop from block import queue: {0}")] - FailedToPopBlockImportQueue(#[from] itp_block_import_queue::error::Error), + FailedToPopBlockImportQueue(#[from] itp_import_queue::error::Error), #[error("Verification Error: {0}")] VerificationError(its_block_verification::error::Error), }