From 950bcece1683cbbced2d485358d1029649437604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 14 Aug 2020 00:03:50 +0200 Subject: [PATCH] Make parachain validation wasm executor functional (#1574) * Make parachain validation wasm executor functional - Increase the size of the validation result in the shared memory. The validation result holds the new runtime when a runtime upgrade is scheduled. So, we need to give it enough memory to send the data between the validator and the wasm execution host. - Add the `CallInWasmExt`. This is required when doing a runtime upgrade to check that we upgrade to something meaningful. * Update parachain/src/wasm_executor/mod.rs * Update parachain/src/wasm_executor/mod.rs Co-authored-by: Nikolay Volf Co-authored-by: Nikolay Volf --- polkadot/parachain/src/wasm_executor/mod.rs | 13 +++++++----- .../src/wasm_executor/validation_host.rs | 21 +++++++++++++------ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/polkadot/parachain/src/wasm_executor/mod.rs b/polkadot/parachain/src/wasm_executor/mod.rs index 7f53e7829c..a19d6150d0 100644 --- a/polkadot/parachain/src/wasm_executor/mod.rs +++ b/polkadot/parachain/src/wasm_executor/mod.rs @@ -35,6 +35,7 @@ mod validation_host; // maximum memory in bytes const MAX_RUNTIME_MEM: usize = 1024 * 1024 * 1024; // 1 GiB const MAX_CODE_MEM: usize = 16 * 1024 * 1024; // 16 MiB +const MAX_VALIDATION_RESULT_HEADER_MEM: usize = MAX_CODE_MEM + 1024; // 16.001 MiB /// A stub validation-pool defined when compiling for Android or WASM. #[cfg(any(target_os = "android", target_os = "unknown"))] @@ -176,11 +177,6 @@ pub fn validate_candidate_internal( encoded_call_data: &[u8], spawner: impl SpawnNamed + 'static, ) -> Result { - let mut extensions = Extensions::new(); - extensions.register(sp_core::traits::TaskExecutorExt::new(spawner)); - - let mut ext = ValidationExternalities(extensions); - let executor = sc_executor::WasmExecutor::new( sc_executor::WasmExecutionMethod::Interpreted, // TODO: Make sure we don't use more than 1GB: https://github.com/paritytech/polkadot/issues/699 @@ -188,6 +184,13 @@ pub fn validate_candidate_internal( HostFunctions::host_functions(), 8 ); + + let mut extensions = Extensions::new(); + extensions.register(sp_core::traits::TaskExecutorExt::new(spawner)); + extensions.register(sp_core::traits::CallInWasmExt::new(executor.clone())); + + let mut ext = ValidationExternalities(extensions); + let res = executor.call_in_wasm( validation_code, None, diff --git a/polkadot/parachain/src/wasm_executor/validation_host.rs b/polkadot/parachain/src/wasm_executor/validation_host.rs index ad79949d21..238ed65c7a 100644 --- a/polkadot/parachain/src/wasm_executor/validation_host.rs +++ b/polkadot/parachain/src/wasm_executor/validation_host.rs @@ -19,8 +19,10 @@ use std::{process, env, sync::Arc, sync::atomic}; use codec::{Decode, Encode}; use crate::primitives::{ValidationParams, ValidationResult}; -use super::{validate_candidate_internal, ValidationError, InvalidCandidate, InternalError, - MAX_CODE_MEM, MAX_RUNTIME_MEM}; +use super::{ + validate_candidate_internal, ValidationError, InvalidCandidate, InternalError, + MAX_CODE_MEM, MAX_RUNTIME_MEM, MAX_VALIDATION_RESULT_HEADER_MEM, +}; use shared_memory::{SharedMem, SharedMemConf, EventState, WriteLockable, EventWait, EventSet}; use parking_lot::Mutex; use log::{debug, trace}; @@ -113,7 +115,7 @@ pub fn run_worker(mem_id: &str) -> Result<(), String> { }; let exit = Arc::new(atomic::AtomicBool::new(false)); - let task_executor = TaskExecutor::new()?; + let task_executor = TaskExecutor::new()?; // spawn parent monitor thread let watch_exit = exit.clone(); std::thread::spawn(move || { @@ -220,7 +222,7 @@ impl Drop for ValidationHost { impl ValidationHost { fn create_memory() -> Result { - let mem_size = MAX_RUNTIME_MEM + MAX_CODE_MEM + 1024; + let mem_size = MAX_RUNTIME_MEM + MAX_CODE_MEM + MAX_VALIDATION_RESULT_HEADER_MEM; let mem_config = SharedMemConf::default() .set_size(mem_size) .add_lock(shared_memory::LockType::Mutex, 0, mem_size)? @@ -318,9 +320,16 @@ impl ValidationHost { debug!("{} Reading results", self.id); let data: &[u8] = &**memory.wlock_as_slice(0) .map_err(|e| ValidationError::Internal(e.into()))?; - let (header_buf, _) = data.split_at(1024); + let (header_buf, _) = data.split_at(MAX_VALIDATION_RESULT_HEADER_MEM); let mut header_buf: &[u8] = header_buf; - let header = ValidationResultHeader::decode(&mut header_buf).unwrap(); + let header = ValidationResultHeader::decode(&mut header_buf) + .map_err(|e| + InternalError::System( + Box::::from( + format!("Failed to decode `ValidationResultHeader`: {:?}", e) + ) as Box<_> + ) + )?; match header { ValidationResultHeader::Ok(result) => Ok(result), ValidationResultHeader::Error(WorkerValidationError::InternalError(e)) => {