From 7853a482e79f761d1dd14da51c848ad583d72fed Mon Sep 17 00:00:00 2001 From: gaudenzkessler <92718752+gaudenzkessler@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:00:20 +0100 Subject: [PATCH] Update sgxruntime and wasm builder (#32, #34) * update sgx-runtime * wasm-builder Cherry-pick: 74ff735, 24e2f2d Co-authored-by: Gaudenz Kessler --- Cargo.lock | 3 + core-primitives/settings/src/lib.rs | 1 + core-primitives/stf-executor/src/executor.rs | 1 - core-primitives/stf-executor/src/traits.rs | 2 - core-primitives/test/src/mock/mod.rs | 1 + .../test/src/mock/ocall_api_mock.rs | 164 ++++++++++++++++++ .../src/indirect_calls_executor.rs | 5 +- enclave-runtime/Cargo.lock | 4 + enclave-runtime/Cargo.toml | 1 + enclave-runtime/src/global_components.rs | 2 + enclave-runtime/src/test/mocks/types.rs | 8 +- .../src/test/sidechain_aura_tests.rs | 2 + sidechain/consensus/aura/Cargo.toml | 5 + .../consensus/aura/src/block_importer.rs | 134 ++++++++++++-- .../aura/src/test/block_importer_tests.rs | 12 +- .../top-pool-executor/src/call_operator.rs | 10 +- 16 files changed, 334 insertions(+), 21 deletions(-) create mode 100644 core-primitives/test/src/mock/ocall_api_mock.rs diff --git a/Cargo.lock b/Cargo.lock index 8a617e9b35..123b66181b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2900,7 +2900,9 @@ dependencies = [ "frame-support", "ita-stf", "itc-parentchain-block-import-dispatcher", + "itc-parentchain-light-client", "itp-enclave-metrics", + "itp-extrinsics-factory", "itp-ocall-api", "itp-settings", "itp-sgx-crypto", @@ -2919,6 +2921,7 @@ dependencies = [ "its-top-pool-executor", "its-validateer-fetch", "log 0.4.17", + "pallet-ajuna-connectfour", "parity-scale-codec", "sgx-externalities", "sgx_tstd", diff --git a/core-primitives/settings/src/lib.rs b/core-primitives/settings/src/lib.rs index a5360a4a7d..a3c4a8d561 100644 --- a/core-primitives/settings/src/lib.rs +++ b/core-primitives/settings/src/lib.rs @@ -109,6 +109,7 @@ pub mod node { pub static UNSHIELD_FUNDS: u8 = 5u8; pub static GAME_REGISTRY_MODULE: u8 = 13u8; pub static ACK_GAME: u8 = 2u8; + pub static FINISH_GAME: u8 = 4u8; // Sidechain module values pub static SIDECHAIN_MODULE: u8 = 20u8; pub static PROPOSED_SIDECHAIN_BLOCK: u8 = 0u8; diff --git a/core-primitives/stf-executor/src/executor.rs b/core-primitives/stf-executor/src/executor.rs index 29623bf14c..6b2790eefd 100644 --- a/core-primitives/stf-executor/src/executor.rs +++ b/core-primitives/stf-executor/src/executor.rs @@ -211,7 +211,6 @@ where fn execute_new_game( &self, - game_engine: GameEngine, game: H256, shard: &ShardIdentifier, block: &ParentchainBlock, diff --git a/core-primitives/stf-executor/src/traits.rs b/core-primitives/stf-executor/src/traits.rs index e7d01273a9..27379215a0 100644 --- a/core-primitives/stf-executor/src/traits.rs +++ b/core-primitives/stf-executor/src/traits.rs @@ -21,7 +21,6 @@ use ita_stf::{ AccountId, ParentchainHeader, ShardIdentifier, TrustedGetterSigned, TrustedOperation, }; use itp_types::{Amount, OpaqueCall, H256}; -use pallet_ajuna_gameregistry::game::GameEngine; use sgx_externalities::SgxExternalitiesTrait; use sp_runtime::traits::{Block as ParentchainBlockTrait, Header as HeaderTrait}; use std::{fmt::Debug, result::Result as StdResult, time::Duration, vec::Vec}; @@ -43,7 +42,6 @@ pub trait StfExecuteShieldFunds { fn execute_new_game( &self, - game_engine: GameEngine, game: H256, shard: &ShardIdentifier, block: &ParentchainBlock, diff --git a/core-primitives/test/src/mock/mod.rs b/core-primitives/test/src/mock/mod.rs index 2d91b77ff3..e1d63ce5b7 100644 --- a/core-primitives/test/src/mock/mod.rs +++ b/core-primitives/test/src/mock/mod.rs @@ -17,6 +17,7 @@ pub mod handle_state_mock; pub mod metrics_ocall_mock; +pub mod ocall_api_mock; pub mod onchain_mock; pub mod shielding_crypto_mock; pub mod sidechain_ocall_api_mock; diff --git a/core-primitives/test/src/mock/ocall_api_mock.rs b/core-primitives/test/src/mock/ocall_api_mock.rs new file mode 100644 index 0000000000..0d943fe415 --- /dev/null +++ b/core-primitives/test/src/mock/ocall_api_mock.rs @@ -0,0 +1,164 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + 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 codec::{Decode, Encode}; +use core::fmt::Debug; +use itp_ocall_api::{ + EnclaveAttestationOCallApi, EnclaveMetricsOCallApi, EnclaveOnChainOCallApi, + EnclaveSidechainOCallApi, +}; +use itp_teerex_storage::{TeeRexStorage, TeerexStorageKeys}; +use itp_types::{BlockHash, Enclave, ShardIdentifier, WorkerRequest, WorkerResponse}; +use sgx_types::{ + sgx_epid_group_id_t, sgx_measurement_t, sgx_platform_info_t, sgx_quote_nonce_t, + sgx_quote_sign_type_t, sgx_report_t, sgx_spid_t, sgx_target_info_t, sgx_update_info_bit_t, + SgxResult, SGX_HASH_SIZE, +}; +use sp_runtime::{AccountId32, OpaqueExtrinsic}; +use sp_std::prelude::*; +use std::collections::HashMap; + +/// This struct is the same as OnchainMock but +/// implements EnclaveOnChainOCallApi instead of GetStorageVerified. +#[derive(Default, Clone, Debug)] +pub struct OcallApiMock { + inner: HashMap, Vec>, + mr_enclave: [u8; SGX_HASH_SIZE], +} + +impl OcallApiMock { + pub fn with_storage_entries(mut self, entries: Vec<(Vec, V)>) -> Self { + for (k, v) in entries.into_iter() { + self.inner.insert(k, v.encode()); + } + self + } + + pub fn with_validateer_set(mut self, set: Option>) -> Self { + let set = set.unwrap_or_else(validateer_set); + self.inner.insert(TeeRexStorage::enclave_count(), (set.len() as u64).encode()); + self.with_storage_entries(into_key_value_storage(set)) + } + + pub fn with_mr_enclave(mut self, mr_enclave: [u8; SGX_HASH_SIZE]) -> Self { + self.mr_enclave = mr_enclave; + self + } + + pub fn insert(&mut self, key: Vec, value: Vec) { + self.inner.insert(key, value); + } + + pub fn get(&self, key: &[u8]) -> Option<&Vec> { + self.inner.get(key) + } +} + +impl EnclaveAttestationOCallApi for OcallApiMock { + fn sgx_init_quote(&self) -> SgxResult<(sgx_target_info_t, sgx_epid_group_id_t)> { + todo!() + } + + fn get_ias_socket(&self) -> SgxResult { + Ok(42) + } + + fn get_quote( + &self, + _sig_rl: Vec, + _report: sgx_report_t, + _sign_type: sgx_quote_sign_type_t, + _spid: sgx_spid_t, + _quote_nonce: sgx_quote_nonce_t, + ) -> SgxResult<(sgx_report_t, Vec)> { + todo!() + } + + fn get_update_info( + &self, + _platform_info: sgx_platform_info_t, + _enclave_trusted: i32, + ) -> SgxResult { + todo!() + } + + fn get_mrenclave_of_self(&self) -> SgxResult { + Ok(sgx_measurement_t { m: self.mr_enclave }) + } +} + +impl EnclaveSidechainOCallApi for OcallApiMock { + fn propose_sidechain_blocks( + &self, + _signed_blocks: Vec, + ) -> SgxResult<()> { + Ok(()) + } + + fn store_sidechain_blocks( + &self, + _signed_blocks: Vec, + ) -> SgxResult<()> { + Ok(()) + } + + fn fetch_sidechain_blocks_from_peer( + &self, + _last_known_block_hash: BlockHash, + _shard_identifier: ShardIdentifier, + ) -> SgxResult> { + Ok(Vec::new()) + } +} + +impl EnclaveMetricsOCallApi for OcallApiMock { + fn update_metric(&self, _metric: Metric) -> SgxResult<()> { + Ok(()) + } +} + +impl EnclaveOnChainOCallApi for OcallApiMock { + fn send_to_parentchain(&self, _extrinsics: Vec) -> SgxResult<()> { + Ok(()) + } + + fn worker_request( + &self, + _req: Vec, + ) -> SgxResult>> { + Ok(Vec::new()) + } +} + +pub fn validateer_set() -> Vec { + let default_enclave = Enclave::new( + AccountId32::from([0; 32]), + Default::default(), + Default::default(), + Default::default(), + ); + vec![default_enclave.clone(), default_enclave.clone(), default_enclave.clone(), default_enclave] +} + +fn into_key_value_storage(validateers: Vec) -> Vec<(Vec, Enclave)> { + validateers + .into_iter() + .enumerate() + .map(|(i, e)| (TeeRexStorage::enclave(i as u64 + 1), e)) + .collect() +} diff --git a/core/parentchain/indirect-calls-executor/src/indirect_calls_executor.rs b/core/parentchain/indirect-calls-executor/src/indirect_calls_executor.rs index 900453c426..948fba970d 100644 --- a/core/parentchain/indirect-calls-executor/src/indirect_calls_executor.rs +++ b/core/parentchain/indirect-calls-executor/src/indirect_calls_executor.rs @@ -97,13 +97,12 @@ where where ParentchainBlock: ParentchainBlockTrait, { - let (_call, game_engine, games, shard) = &xt.function; + let (_call, _game_engine, games, shard) = &xt.function; info!("found {:?} games", games.len()); for game in games { - self.stf_executor - .execute_new_game(game_engine.clone(), game.clone(), shard, block); + self.stf_executor.execute_new_game(game.clone(), shard, block)?; } Ok(()) } diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index 5d009dbf3d..03deeef56f 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -541,6 +541,7 @@ dependencies = [ "ita-stf", "itc-direct-rpc-server", "itc-parentchain", + "itc-parentchain-light-client", "itc-tls-websocket-server", "itertools", "itp-block-import-queue", @@ -1633,7 +1634,9 @@ dependencies = [ "frame-support", "ita-stf", "itc-parentchain-block-import-dispatcher", + "itc-parentchain-light-client", "itp-enclave-metrics", + "itp-extrinsics-factory", "itp-ocall-api", "itp-settings", "itp-sgx-crypto", @@ -1649,6 +1652,7 @@ dependencies = [ "its-top-pool-executor", "its-validateer-fetch", "log 0.4.14 (git+https://github.com/mesalock-linux/log-sgx)", + "pallet-ajuna-connectfour", "sgx-externalities", "sgx_tstd", "sp-core", diff --git a/enclave-runtime/Cargo.toml b/enclave-runtime/Cargo.toml index 7973779f45..80e43a9940 100644 --- a/enclave-runtime/Cargo.toml +++ b/enclave-runtime/Cargo.toml @@ -87,6 +87,7 @@ ita-stf = { path = "../app-libs/stf", default-features = false, features = ["sgx itc-tls-websocket-server = { path = "../core/tls-websocket-server", default-features = false, features = ["sgx"] } itc-direct-rpc-server = { path = "../core/direct-rpc-server", default-features = false, features = ["sgx"] } itc-parentchain = { path = "../core/parentchain/parentchain-crate", default-features = false, features = ["sgx"] } +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, 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"]} diff --git a/enclave-runtime/src/global_components.rs b/enclave-runtime/src/global_components.rs index f156a9b293..9168f58ce0 100644 --- a/enclave-runtime/src/global_components.rs +++ b/enclave-runtime/src/global_components.rs @@ -126,6 +126,8 @@ pub type EnclaveSidechainBlockImporter = SidechainBlockImporter< EnclaveStateKeyRepository, EnclaveTopPoolOperationHandler, EnclaveParentchainBlockImportDispatcher, + EnclaveExtrinsicsFactory, + ValidatorAccessor, >; pub type EnclaveSidechainBlockImportQueue = BlockImportQueue; pub type EnclaveSidechainBlockSyncer = PeerBlockSync< diff --git a/enclave-runtime/src/test/mocks/types.rs b/enclave-runtime/src/test/mocks/types.rs index 920bdb6616..bf9222d6fe 100644 --- a/enclave-runtime/src/test/mocks/types.rs +++ b/enclave-runtime/src/test/mocks/types.rs @@ -20,11 +20,13 @@ use crate::test::mocks::rpc_responder_mock::RpcResponderMock; use itc_parentchain::block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; +use itc_parentchain_light_client::mocks::validator_access_mock::ValidatorAccessMock; +use itp_extrinsics_factory::mock::ExtrinsicsFactoryMock; use itp_sgx_crypto::{mocks::KeyRepositoryMock, Aes}; use itp_stf_executor::executor::StfExecutor; use itp_test::mock::{ handle_state_mock::HandleStateMock, metrics_ocall_mock::MetricsOCallMock, - onchain_mock::OnchainMock, + ocall_api_mock::OcallApiMock, }; use itp_top_pool::basic_pool::BasicPool; use itp_top_pool_author::{ @@ -56,7 +58,7 @@ pub type TestStateHandler = HandleStateMock; pub type TestSidechainDb = SidechainDB; -pub type TestOCallApi = OnchainMock; +pub type TestOCallApi = OcallApiMock; pub type TestParentchainBlockImportTrigger = TriggerParentchainBlockImportMock; @@ -91,4 +93,6 @@ pub type TestBlockImporter = BlockImporter< TestStateKeyRepo, TestTopPoolExecutor, TestParentchainBlockImportTrigger, + ExtrinsicsFactoryMock, + ValidatorAccessMock, >; diff --git a/enclave-runtime/src/test/sidechain_aura_tests.rs b/enclave-runtime/src/test/sidechain_aura_tests.rs index b19ffdd2bd..f76d709693 100644 --- a/enclave-runtime/src/test/sidechain_aura_tests.rs +++ b/enclave-runtime/src/test/sidechain_aura_tests.rs @@ -100,6 +100,8 @@ pub fn produce_sidechain_block_and_import_it() { top_pool_operation_handler.clone(), parentchain_block_import_trigger.clone(), ocall_api.clone(), + Arc::new(ExtrinsicsFactoryMock::default()), + Arc::new(ValidatorAccessMock::default()), )); let block_composer = Arc::new(TestBlockComposer::new(signer.clone(), state_key_repo.clone())); let proposer_environment = diff --git a/sidechain/consensus/aura/Cargo.toml b/sidechain/consensus/aura/Cargo.toml index c7af24a035..2b13ba5499 100644 --- a/sidechain/consensus/aura/Cargo.toml +++ b/sidechain/consensus/aura/Cargo.toml @@ -20,7 +20,9 @@ sp-runtime = { version = "6.0.0", default-features = false, git = "https://githu # local deps ita-stf = { path = "../../../app-libs/stf", default-features = false } itc-parentchain-block-import-dispatcher = { path = "../../../core/parentchain/block-import-dispatcher", default-features = false } +itc-parentchain-light-client = { path = "../../../core/parentchain/light-client", default-features = false } itp-enclave-metrics = { path = "../../../core-primitives/enclave-metrics", default-features = false } +itp-extrinsics-factory = { path = "../../../core-primitives/extrinsics-factory", default-features = false } itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } itp-settings = { path = "../../../core-primitives/settings" } itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } @@ -36,6 +38,8 @@ its-state = { path = "../../state", default-features = false } its-top-pool-executor = { path = "../../top-pool-executor", default-features = false } its-validateer-fetch = { path = "../../validateer-fetch", default-features = false } +pallet-ajuna-connectfour = { default-features = false, git = "https://github.com/ajuna-network/Ajuna", rev = "polkadot-v0.9.20" } + [dev-dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } env_logger = "0.9.0" @@ -66,6 +70,7 @@ std = [ "its-top-pool-executor/std", "its-validateer-fetch/std", "log/std", + "pallet-ajuna-connectfour/std", "sgx-externalities/std", ] sgx = [ diff --git a/sidechain/consensus/aura/src/block_importer.rs b/sidechain/consensus/aura/src/block_importer.rs index b68988c38f..aa1803e03f 100644 --- a/sidechain/consensus/aura/src/block_importer.rs +++ b/sidechain/consensus/aura/src/block_importer.rs @@ -20,18 +20,25 @@ // Reexport BlockImport trait which implements fn block_import() pub use its_consensus_common::BlockImport; -use crate::{AuraVerifier, EnclaveOnChainOCallApi, SidechainBlockTrait}; -use ita_stf::hash::TrustedOperationOrHash; +use ita_stf::{ + hash::TrustedOperationOrHash, helpers::get_board_for, ParentchainHeader, SgxBoardStruct, + TrustedCall, TrustedCallSigned, +}; use itc_parentchain_block_import_dispatcher::triggered_dispatcher::{ PeekParentchainBlockImportQueue, TriggerParentchainBlockImport, }; +use itc_parentchain_light_client::{concurrent_access::ValidatorAccess, Validator}; use itp_enclave_metrics::EnclaveMetric; -use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveSidechainOCallApi}; -use itp_settings::sidechain::SLOT_DURATION; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveOnChainOCallApi, EnclaveSidechainOCallApi}; +use itp_settings::{ + node::{FINISH_GAME, GAME_REGISTRY_MODULE}, + sidechain::SLOT_DURATION, +}; use itp_sgx_crypto::{key_repository::AccessKey, StateCrypto}; use itp_stf_executor::ExecutedOperation; use itp_stf_state_handler::handle_state::HandleState; -use itp_types::H256; +use itp_types::{OpaqueCall, H256}; use its_consensus_common::Error as ConsensusError; use its_primitives::traits::{ BlockData, Header as HeaderTrait, ShardIdentifierFor, SignedBlock as SignedBlockTrait, @@ -40,11 +47,11 @@ use its_state::SidechainDB; use its_top_pool_executor::TopPoolCallOperator; use its_validateer_fetch::ValidateerFetch; use log::*; -use sgx_externalities::SgxExternalities; +use pallet_ajuna_connectfour::BoardState; +use sgx_externalities::{SgxExternalities, SgxExternalitiesTrait}; use sp_core::Pair; use sp_runtime::{ - generic::SignedBlock as SignedParentchainBlock, - traits::{Block as ParentchainBlockTrait, Header}, + generic::SignedBlock as SignedParentchainBlock, traits::Block as ParentchainBlockTrait, }; use std::{marker::PhantomData, sync::Arc, vec::Vec}; @@ -60,6 +67,8 @@ pub struct BlockImporter< StateKeyRepository, TopPoolExecutor, ParentchainBlockImporter, + ExtrinsicsFactory, + ValidatorAccessor, > { state_handler: Arc, state_key_repository: Arc, @@ -67,6 +76,8 @@ pub struct BlockImporter< parentchain_block_importer: Arc, ocall_api: Arc, _phantom: PhantomData<(Authority, ParentchainBlock, SignedSidechainBlock, SidechainState)>, + extrinsics_factory: Arc, + validator_accessor: Arc, } impl< @@ -79,6 +90,8 @@ impl< StateKeyRepository, TopPoolExecutor, ParentchainBlockImporter, + ExtrinsicsFactory, + ValidatorAccessor, > BlockImporter< Authority, @@ -90,10 +103,12 @@ impl< StateKeyRepository, TopPoolExecutor, ParentchainBlockImporter, + ExtrinsicsFactory, + ValidatorAccessor, > where Authority: Pair, Authority::Public: std::fmt::Debug, - ParentchainBlock: ParentchainBlockTrait, + ParentchainBlock: ParentchainBlockTrait, SignedSidechainBlock: SignedBlockTrait + 'static, <::Block as SidechainBlockTrait>::HeaderType: HeaderTrait, @@ -112,6 +127,8 @@ impl< + PeekParentchainBlockImportQueue> + Send + Sync, + ExtrinsicsFactory: CreateExtrinsics, + ValidatorAccessor: ValidatorAccess, { pub fn new( state_handler: Arc, @@ -119,6 +136,8 @@ impl< top_pool_executor: Arc, parentchain_block_importer: Arc, ocall_api: Arc, + extrinsics_factory: Arc, + validator_accessor: Arc, ) -> Self { Self { state_handler, @@ -127,6 +146,8 @@ impl< parentchain_block_importer, ocall_api, _phantom: Default::default(), + extrinsics_factory, + validator_accessor, } } @@ -158,6 +179,87 @@ impl< ); } } + + fn get_calls_in_block( + &self, + sidechain_block: &::Block, + ) -> Result, ConsensusError> { + let shard = &sidechain_block.shard_id(); + let top_hashes = sidechain_block.signed_top_hashes(); + let calls = self + .top_pool_executor + .get_trusted_calls(shard) + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + + Ok(calls + .iter() + .filter(|call| { + top_hashes.contains(&self.top_pool_executor.get_trusted_call_hash(&call)) + }) + .map(|call| call.clone()) + .collect()) + } + + fn get_board_if_game_finished( + &self, + sidechain_block: &::Block, + call: &TrustedCallSigned, + ) -> Result, ConsensusError> { + let shard = &sidechain_block.shard_id(); + if let TrustedCall::connectfour_play_turn(account, _b) = &call.call { + let mut state = self + .state_handler + .load_initialized(&shard) + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + if let Some(board) = state.execute_with(|| get_board_for(account.clone())) { + if let BoardState::Finished(_) = board.board_state { + return Ok(Some(board)) + } + } else { + error!("could not decode board. maybe hasn't been set?"); + } + } + Ok(None) + } + + fn send_game_finished_extrinsic( + &self, + sidechain_block: &::Block, + board: SgxBoardStruct, + ) -> Result<(), ConsensusError> { + let shard = &sidechain_block.shard_id(); + // player 1 is red, player 2 is blue + // the winner is not the next player + let winner = match board.next_player { + 1 => board.blue, + 2 => board.red, + _ => + return Err(ConsensusError::BadSidechainBlock( + sidechain_block.hash(), + "Unknown player, could not get the Winner.".to_string(), + )), + }; + + let opaque_call = + OpaqueCall::from_tuple(&([GAME_REGISTRY_MODULE, FINISH_GAME], shard, winner)); + + let calls = vec![opaque_call]; + + // Create extrinsic for finish game. + let finish_game_extrinsic = self + .extrinsics_factory + .create_extrinsics(calls.as_slice()) + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + + // Sending the extrinsic requires mut access because the validator caches the sent extrinsics internally. + self.validator_accessor + .execute_mut_on_validator(|v| { + v.send_extrinsics(self.ocall_api.as_ref(), finish_game_extrinsic) + }) + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + trace!("extrinsic finish game sent"); + Ok(()) + } } impl< @@ -169,6 +271,8 @@ impl< StateKeyRepository, TopPoolExecutor, ParentchainBlockImporter, + ExtrinsicsFactory, + ValidatorAccessor, > BlockImport for BlockImporter< Authority, @@ -180,10 +284,12 @@ impl< StateKeyRepository, TopPoolExecutor, ParentchainBlockImporter, + ExtrinsicsFactory, + ValidatorAccessor, > where Authority: Pair, Authority::Public: std::fmt::Debug, - ParentchainBlock: ParentchainBlockTrait, + ParentchainBlock: ParentchainBlockTrait, SignedSidechainBlock: SignedBlockTrait + 'static, <::Block as SidechainBlockTrait>::HeaderType: HeaderTrait, @@ -202,6 +308,8 @@ impl< + PeekParentchainBlockImportQueue> + Send + Sync, + ExtrinsicsFactory: CreateExtrinsics, + ValidatorAccessor: ValidatorAccess, { type Verifier = AuraVerifier< Authority, @@ -323,6 +431,12 @@ impl< fn cleanup(&self, signed_sidechain_block: &SignedSidechainBlock) -> Result<(), ConsensusError> { let sidechain_block = signed_sidechain_block.block(); + for call in self.get_calls_in_block(sidechain_block)? { + if let Some(board) = self.get_board_if_game_finished(sidechain_block, &call)? { + self.send_game_finished_extrinsic(sidechain_block, board)?; + } + } + // Remove all successfully applied trusted calls from the top pool. self.update_top_pool(sidechain_block); diff --git a/sidechain/consensus/aura/src/test/block_importer_tests.rs b/sidechain/consensus/aura/src/test/block_importer_tests.rs index 22bc3fee85..c88de188d7 100644 --- a/sidechain/consensus/aura/src/test/block_importer_tests.rs +++ b/sidechain/consensus/aura/src/test/block_importer_tests.rs @@ -15,10 +15,16 @@ */ -use crate::{block_importer::BlockImporter, test::fixtures::validateer, ShardIdentifierFor}; +use crate::{ + block_importer::BlockImporter, + test::{fixtures::validateer, mocks::onchain_mock::OnchainMock}, + ShardIdentifierFor, +}; use codec::Encode; use core::assert_matches::assert_matches; use itc_parentchain_block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; +use itc_parentchain_light_client::mocks::validator_access_mock::ValidatorAccessMock; +use itp_extrinsics_factory::mock::ExtrinsicsFactoryMock; use itp_sgx_crypto::{aes::Aes, mocks::KeyRepositoryMock, StateCrypto}; use itp_stf_state_handler::handle_state::HandleState; use itp_test::{ @@ -26,7 +32,7 @@ use itp_test::{ parentchain_block_builder::ParentchainBlockBuilder, parentchain_header_builder::ParentchainHeaderBuilder, }, - mock::{handle_state_mock::HandleStateMock, onchain_mock::OnchainMock}, + mock::handle_state_mock::HandleStateMock, }; use itp_time_utils::{duration_now, now_as_u64}; use itp_types::{Block as ParentchainBlock, Header as ParentchainHeader, H256}; @@ -94,6 +100,8 @@ fn test_fixtures( top_pool_call_operator.clone(), parentchain_block_import_trigger, ocall_api, + Arc::new(ExtrinsicsFactoryMock::default()), + Arc::new(ValidatorAccessMock::default()), ); (block_importer, state_handler, top_pool_call_operator) diff --git a/sidechain/top-pool-executor/src/call_operator.rs b/sidechain/top-pool-executor/src/call_operator.rs index e563bbf8c6..c7c380ac34 100644 --- a/sidechain/top-pool-executor/src/call_operator.rs +++ b/sidechain/top-pool-executor/src/call_operator.rs @@ -16,7 +16,7 @@ */ use crate::{error::Result, TopPoolOperationHandler}; -use ita_stf::TrustedOperation; +use ita_stf::{TrustedCallSigned, TrustedOperation}; use itp_stf_executor::traits::{StateUpdateProposer, StfExecuteTimedGettersBatch}; use itp_top_pool_author::traits::{AuthorApi, OnBlockImported, SendState}; use itp_types::H256; @@ -45,6 +45,9 @@ pub trait TopPoolCallOperator< shard: &ShardIdentifierFor, ) -> Result>; + /// Retrieves the hash of trusted calls. + fn get_trusted_call_hash(&self, call: &TrustedCallSigned) -> H256; + /// Removes the given trusted calls from the top pool. /// Returns all hashes that were NOT successfully removed. fn remove_calls_from_pool( @@ -81,6 +84,11 @@ where Ok(self.top_pool_author.get_pending_tops_separated(*shard)?.0) } + fn get_trusted_call_hash(&self, call: &TrustedCallSigned) -> H256 { + let top: TrustedOperation = TrustedOperation::direct_call(call.clone()); + self.rpc_author.hash_of(&top) + } + fn remove_calls_from_pool( &self, shard: &ShardIdentifierFor,