From e10bddd5b8498a54d9266a0c631ae753ba487458 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Mon, 6 Jan 2020 13:41:42 +0100 Subject: [PATCH 01/41] WIP --- client/executor/runtime-test/src/lib.rs | 9 ++++++ client/executor/src/integration_tests/mod.rs | 19 +++++++++++++ client/executor/wasmi/src/lib.rs | 30 +++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index c49b9e70b4f85..ca802f9d6c0a4 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -18,7 +18,16 @@ use sp_runtime::{print, traits::{BlakeTwo256, Hash}}; #[cfg(not(feature = "std"))] use sp_core::{ed25519, sr25519}; +extern "C" { + #[allow(dead_code)] + fn missing_external(); +} + sp_core::wasm_export_functions! { + fn test_calling_missing_external() { + unsafe { missing_external() } + } + fn test_data_in(input: Vec) -> Vec { print("set_storage"); storage::set(b"input", &input); diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 24e9e022f7063..ceb0cb3ddb2e6 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -68,6 +68,25 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) { assert_eq!(output, vec![0u8; 0]); } +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn not_existing_functions_should_return_stub(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let output = call_in_wasm( + "test_calling_missing_external", + &[], + wasm_method, + &mut ext, + &test_code[..], + 8, + ); + panic!("{:?}", output); + assert!(output.is_err()); +} + #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] fn panicking_should_work(wasm_method: WasmExecutionMethod) { diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 97191531041f5..e18a76bfb1bc9 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -276,6 +276,7 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { -> std::result::Result { let signature = sp_wasm_interface::Signature::from(signature); + eprintln!("resolve: {}", name); for (function_index, function) in self.0.iter().enumerate() { if name == function.name() { if signature == function.signature() { @@ -295,9 +296,16 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { } } + //panic!("boo {} {:?}", name, signature); + let (function_index, _) = self.0.iter().enumerate().find(|(_, x)| x.name() == "stub_function").expect("cant find fallback function"); + Ok( + wasmi::FuncInstance::alloc_host(signature.into(), function_index), + ) + /* Err(wasmi::Error::Instantiation( format!("Export {} not found", name), )) + */ } } @@ -392,6 +400,24 @@ fn call_in_wasm_module( } } +struct StubFunction; + +impl Function for StubFunction { + fn name(&self) -> &'static str { "stub_function" } + + fn signature(&self) -> sp_wasm_interface::Signature { sp_wasm_interface::Signature::new_with_args(vec![]) } + + fn execute( + &self, + context: &mut dyn FunctionContext, + args: &mut dyn Iterator, + ) -> sp_wasm_interface::Result> { + panic!("boo"); + } +} + +static STUB: &'static StubFunction = &StubFunction; + /// Prepare module instance fn instantiate_module( heap_pages: usize, @@ -568,8 +594,10 @@ impl WasmRuntime for WasmiRuntime { pub fn create_instance( code: &[u8], heap_pages: u64, - host_functions: Vec<&'static dyn Function>, + mut host_functions: Vec<&'static dyn Function>, ) -> Result { + host_functions.push(STUB); + eprintln!("{:?}", host_functions.iter().map(|x| x.name()).collect::>()); let module = Module::from_buffer(&code).map_err(|_| WasmError::InvalidModule)?; // Extract the data segments from the wasm code. From 86b6bc5d929959e96b8a377ec37bee5cf171c19e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Mon, 6 Jan 2020 15:15:47 +0100 Subject: [PATCH 02/41] WIP --- client/executor/common/src/wasm_runtime.rs | 3 + client/executor/src/integration_tests/mod.rs | 1 + client/executor/src/lib.rs | 3 + client/executor/src/wasm_runtime.rs | 11 +++- client/executor/wasmi/src/lib.rs | 64 ++++++++++++-------- 5 files changed, 56 insertions(+), 26 deletions(-) diff --git a/client/executor/common/src/wasm_runtime.rs b/client/executor/common/src/wasm_runtime.rs index 0df7d21ac2f37..cc6b0c7061a05 100644 --- a/client/executor/common/src/wasm_runtime.rs +++ b/client/executor/common/src/wasm_runtime.rs @@ -36,4 +36,7 @@ pub trait WasmRuntime { /// Call a method in the Substrate runtime by name. Returns the encoded result on success. fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result, Error>; + + /// Enable STUB for function called that are missing + fn enable_stub(&mut self); } diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index ceb0cb3ddb2e6..e42373b0befbe 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -47,6 +47,7 @@ fn call_in_wasm( ext, code, heap_pages, + true, ) } diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs index c343e97b44c3a..b9aa04e9c8dff 100644 --- a/client/executor/src/lib.rs +++ b/client/executor/src/lib.rs @@ -67,12 +67,14 @@ pub fn call_in_wasm( ext: &mut E, code: &[u8], heap_pages: u64, + enable_stub: bool, ) -> error::Result> { let mut instance = wasm_runtime::create_wasm_runtime_with_code( execution_method, heap_pages, code, HF::host_functions(), + enable_stub, )?; instance.call(ext, function, call_data) } @@ -103,6 +105,7 @@ mod tests { &mut ext, &WASM_BINARY, 8, + false, ).unwrap(); assert_eq!(res, vec![0u8; 0]); } diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 4c7e80f925337..33c214f6decf9 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -191,8 +191,9 @@ pub fn create_wasm_runtime_with_code( heap_pages: u64, code: &[u8], host_functions: Vec<&'static dyn Function>, + enable_stub: bool, ) -> Result, WasmError> { - match wasm_method { + let mut runtime = match wasm_method { WasmExecutionMethod::Interpreted => sc_executor_wasmi::create_instance(code, heap_pages, host_functions) .map(|runtime| -> Box { Box::new(runtime) }), @@ -200,7 +201,13 @@ pub fn create_wasm_runtime_with_code( WasmExecutionMethod::Compiled => sc_executor_wasmtime::create_instance(code, heap_pages, host_functions) .map(|runtime| -> Box { Box::new(runtime) }), + }?; + + if enable_stub { + runtime.enable_stub(); } + + Ok(runtime) } fn create_versioned_wasm_runtime( @@ -212,7 +219,7 @@ fn create_versioned_wasm_runtime( let code = ext .original_storage(well_known_keys::CODE) .ok_or(WasmError::CodeNotFound)?; - let mut runtime = create_wasm_runtime_with_code(wasm_method, heap_pages, &code, host_functions)?; + let mut runtime = create_wasm_runtime_with_code(wasm_method, heap_pages, &code, host_functions, false)?; // Call to determine runtime version. let version_result = { diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index e18a76bfb1bc9..66ce8773ae4df 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -42,6 +42,7 @@ struct FunctionExecutor<'a> { memory: MemoryRef, table: Option, host_functions: &'a [&'static dyn Function], + enable_stub: bool, } impl<'a> FunctionExecutor<'a> { @@ -50,6 +51,7 @@ impl<'a> FunctionExecutor<'a> { heap_base: u32, t: Option, host_functions: &'a [&'static dyn Function], + enable_stub: bool, ) -> Result { Ok(FunctionExecutor { sandbox_store: sandbox::Store::new(), @@ -57,6 +59,7 @@ impl<'a> FunctionExecutor<'a> { memory: m, table: t, host_functions, + enable_stub, }) } } @@ -269,7 +272,7 @@ impl<'a> Sandbox for FunctionExecutor<'a> { } } -struct Resolver<'a>(&'a[&'static dyn Function]); +struct Resolver<'a>(&'a[&'static dyn Function], bool); impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { fn resolve_func(&self, name: &str, signature: &wasmi::Signature) @@ -296,16 +299,21 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { } } - //panic!("boo {} {:?}", name, signature); - let (function_index, _) = self.0.iter().enumerate().find(|(_, x)| x.name() == "stub_function").expect("cant find fallback function"); - Ok( - wasmi::FuncInstance::alloc_host(signature.into(), function_index), - ) - /* - Err(wasmi::Error::Instantiation( - format!("Export {} not found", name), - )) - */ + if self.1 { + eprintln!("Could not find function {}. The existing functions are: {}", + name, + self.0.iter() + .map(|x| + x.name()).collect::>().join(",")); + + Ok( + wasmi::FuncInstance::alloc_host(signature.into(), self.0.len()), + ) + } else { + Err(wasmi::Error::Instantiation( + format!("Export {} not found", name), + )) + } } } @@ -314,16 +322,17 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { -> Result, wasmi::Trap> { let mut args = args.as_ref().iter().copied().map(Into::into); - let function = self.host_functions.get(index).ok_or_else(|| - Error::from( - format!("Could not find host function with index: {}", index), - ) - )?; - function.execute(self, &mut args) - .map_err(|msg| Error::FunctionExecution(function.name().to_string(), msg)) - .map_err(wasmi::Trap::from) - .map(|v| v.map(Into::into)) + if let Some(function) = self.host_functions.get(index) { + function.execute(self, &mut args) + .map_err(|msg| Error::FunctionExecution(function.name().to_string(), msg)) + .map_err(wasmi::Trap::from) + .map(|v| v.map(Into::into)) + } else if self.enable_stub { + panic!("function does not exist"); + } else { + Err(Error::from(format!("Could not find host function with index: {}", index)).into()) + } } } @@ -359,6 +368,7 @@ fn call_in_wasm_module( method: &str, data: &[u8], host_functions: &[&'static dyn Function], + enable_stub: bool, ) -> Result, Error> { // extract a reference to a linear memory, optional reference to a table // and then initialize FunctionExecutor. @@ -368,7 +378,8 @@ fn call_in_wasm_module( .and_then(|e| e.as_table().cloned()); let heap_base = get_heap_base(module_instance)?; - let mut fec = FunctionExecutor::new(memory.clone(), heap_base, table, host_functions)?; + let mut fec = FunctionExecutor::new( + memory.clone(), heap_base, table, host_functions, enable_stub)?; // Write the call data let offset = fec.allocate_memory(data.len() as u32)?; @@ -562,6 +573,7 @@ pub struct WasmiRuntime { state_snapshot: StateSnapshot, /// The host functions registered for this instance. host_functions: Vec<&'static dyn Function>, + enable_stub: bool, } impl WasmRuntime for WasmiRuntime { @@ -587,7 +599,12 @@ impl WasmRuntime for WasmiRuntime { error!(target: "wasm-executor", "snapshot restoration failed: {}", e); e })?; - call_in_wasm_module(ext, &self.instance, method, data, &self.host_functions) + call_in_wasm_module( + ext, &self.instance, method, data, &self.host_functions, self.enable_stub) + } + + fn enable_stub(&mut self) { + self.enable_stub = true; } } @@ -596,8 +613,6 @@ pub fn create_instance( heap_pages: u64, mut host_functions: Vec<&'static dyn Function>, ) -> Result { - host_functions.push(STUB); - eprintln!("{:?}", host_functions.iter().map(|x| x.name()).collect::>()); let module = Module::from_buffer(&code).map_err(|_| WasmError::InvalidModule)?; // Extract the data segments from the wasm code. @@ -623,6 +638,7 @@ pub fn create_instance( instance, state_snapshot, host_functions, + enable_stub: false, }) } From 2e61dca55ac30636d0924101f7e3a51ff75c56d3 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Mon, 6 Jan 2020 15:39:17 +0100 Subject: [PATCH 03/41] WIP --- client/executor/common/src/wasm_runtime.rs | 3 -- client/executor/src/integration_tests/mod.rs | 40 +++++++++++++++++++- client/executor/src/wasm_runtime.rs | 10 +---- client/executor/wasmi/src/lib.rs | 33 ++++------------ 4 files changed, 47 insertions(+), 39 deletions(-) diff --git a/client/executor/common/src/wasm_runtime.rs b/client/executor/common/src/wasm_runtime.rs index cc6b0c7061a05..0df7d21ac2f37 100644 --- a/client/executor/common/src/wasm_runtime.rs +++ b/client/executor/common/src/wasm_runtime.rs @@ -36,7 +36,4 @@ pub trait WasmRuntime { /// Call a method in the Substrate runtime by name. Returns the encoded result on success. fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result, Error>; - - /// Enable STUB for function called that are missing - fn enable_stub(&mut self); } diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index e42373b0befbe..e024879104409 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -39,6 +39,25 @@ fn call_in_wasm( ext: &mut E, code: &[u8], heap_pages: u64, +) -> crate::error::Result> { + crate::call_in_wasm::( + function, + call_data, + execution_method, + ext, + code, + heap_pages, + false, + ) +} + +fn call_in_wasm_with_stub( + function: &str, + call_data: &[u8], + execution_method: WasmExecutionMethod, + ext: &mut E, + code: &[u8], + heap_pages: u64, ) -> crate::error::Result> { crate::call_in_wasm::( function, @@ -71,7 +90,25 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) { #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -fn not_existing_functions_should_return_stub(wasm_method: WasmExecutionMethod) { +#[should_panic(expected = "function does not exist")] +fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let _output = call_in_wasm_with_stub( + "test_calling_missing_external", + &[], + wasm_method, + &mut ext, + &test_code[..], + 8, + ); +} + +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +fn call_not_existing_function_without_stub_enabled(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); let test_code = WASM_BINARY; @@ -84,7 +121,6 @@ fn not_existing_functions_should_return_stub(wasm_method: WasmExecutionMethod) { &test_code[..], 8, ); - panic!("{:?}", output); assert!(output.is_err()); } diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 33c214f6decf9..18d53a7745333 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -193,21 +193,15 @@ pub fn create_wasm_runtime_with_code( host_functions: Vec<&'static dyn Function>, enable_stub: bool, ) -> Result, WasmError> { - let mut runtime = match wasm_method { + match wasm_method { WasmExecutionMethod::Interpreted => - sc_executor_wasmi::create_instance(code, heap_pages, host_functions) + sc_executor_wasmi::create_instance(code, heap_pages, host_functions, enable_stub) .map(|runtime| -> Box { Box::new(runtime) }), #[cfg(feature = "wasmtime")] WasmExecutionMethod::Compiled => sc_executor_wasmtime::create_instance(code, heap_pages, host_functions) .map(|runtime| -> Box { Box::new(runtime) }), - }?; - - if enable_stub { - runtime.enable_stub(); } - - Ok(runtime) } fn create_versioned_wasm_runtime( diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 66ce8773ae4df..91290fd401958 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -411,31 +411,14 @@ fn call_in_wasm_module( } } -struct StubFunction; - -impl Function for StubFunction { - fn name(&self) -> &'static str { "stub_function" } - - fn signature(&self) -> sp_wasm_interface::Signature { sp_wasm_interface::Signature::new_with_args(vec![]) } - - fn execute( - &self, - context: &mut dyn FunctionContext, - args: &mut dyn Iterator, - ) -> sp_wasm_interface::Result> { - panic!("boo"); - } -} - -static STUB: &'static StubFunction = &StubFunction; - /// Prepare module instance fn instantiate_module( heap_pages: usize, module: &Module, host_functions: &[&'static dyn Function], + enable_stub: bool, ) -> Result { - let resolver = Resolver(host_functions); + let resolver = Resolver(host_functions, enable_stub); // start module instantiation. Don't run 'start' function yet. let intermediate_instance = ModuleInstance::new( module, @@ -573,6 +556,7 @@ pub struct WasmiRuntime { state_snapshot: StateSnapshot, /// The host functions registered for this instance. host_functions: Vec<&'static dyn Function>, + /// Enable STUB for function called that are missing enable_stub: bool, } @@ -602,16 +586,13 @@ impl WasmRuntime for WasmiRuntime { call_in_wasm_module( ext, &self.instance, method, data, &self.host_functions, self.enable_stub) } - - fn enable_stub(&mut self) { - self.enable_stub = true; - } } pub fn create_instance( code: &[u8], heap_pages: u64, - mut host_functions: Vec<&'static dyn Function>, + host_functions: Vec<&'static dyn Function>, + enable_stub: bool, ) -> Result { let module = Module::from_buffer(&code).map_err(|_| WasmError::InvalidModule)?; @@ -622,7 +603,7 @@ pub fn create_instance( let data_segments = extract_data_segments(&code)?; // Instantiate this module. - let instance = instantiate_module(heap_pages as usize, &module, &host_functions) + let instance = instantiate_module(heap_pages as usize, &module, &host_functions, enable_stub) .map_err(|e| WasmError::Instantiation(e.to_string()))?; // Take state snapshot before executing anything. @@ -638,7 +619,7 @@ pub fn create_instance( instance, state_snapshot, host_functions, - enable_stub: false, + enable_stub, }) } From ce243f47d138c78fa9935df20d11bf23daeb7762 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 08:56:27 +0100 Subject: [PATCH 04/41] WIP --- client/executor/runtime-test/src/lib.rs | 7 +++++++ client/executor/src/integration_tests/mod.rs | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index ca802f9d6c0a4..a8d329cdd9607 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -21,6 +21,9 @@ use sp_core::{ed25519, sr25519}; extern "C" { #[allow(dead_code)] fn missing_external(); + + #[allow(dead_code)] + fn yet_another_missing_external(); } sp_core::wasm_export_functions! { @@ -28,6 +31,10 @@ sp_core::wasm_export_functions! { unsafe { missing_external() } } + fn test_calling_yet_another_missing_external() { + unsafe { yet_another_missing_external() } + } + fn test_data_in(input: Vec) -> Vec { print("set_storage"); storage::set(b"input", &input); diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index e024879104409..d6a638de45b2e 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -106,6 +106,24 @@ fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod ); } +#[test_case(WasmExecutionMethod::Interpreted)] +#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] +#[should_panic(expected = "function does not exist")] +fn call_yet_another_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { + let mut ext = TestExternalities::default(); + let mut ext = ext.ext(); + let test_code = WASM_BINARY; + + let _output = call_in_wasm_with_stub( + "test_calling_yet_another_missing_external", + &[], + wasm_method, + &mut ext, + &test_code[..], + 8, + ); +} + #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] fn call_not_existing_function_without_stub_enabled(wasm_method: WasmExecutionMethod) { From e19948e8efa91f2ef745db609967bc7726285311 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 11:18:27 +0100 Subject: [PATCH 05/41] WIP --- client/executor/src/integration_tests/mod.rs | 4 +-- client/executor/wasmi/src/lib.rs | 33 +++++++++++--------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index d6a638de45b2e..e9f1d367692a7 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -90,7 +90,7 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) { #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "function does not exist")] +#[should_panic(expected = "function test_calling_missing_external does not exist")] fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -108,7 +108,7 @@ fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "function does not exist")] +#[should_panic(expected = "function test_calling_yet_another_missing_external does not exist")] fn call_yet_another_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 91290fd401958..33ebfa041efdd 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -43,6 +43,7 @@ struct FunctionExecutor<'a> { table: Option, host_functions: &'a [&'static dyn Function], enable_stub: bool, + method: &'a str, } impl<'a> FunctionExecutor<'a> { @@ -52,6 +53,7 @@ impl<'a> FunctionExecutor<'a> { t: Option, host_functions: &'a [&'static dyn Function], enable_stub: bool, + method: &'a str, ) -> Result { Ok(FunctionExecutor { sandbox_store: sandbox::Store::new(), @@ -60,6 +62,7 @@ impl<'a> FunctionExecutor<'a> { table: t, host_functions, enable_stub, + method, }) } } @@ -272,15 +275,17 @@ impl<'a> Sandbox for FunctionExecutor<'a> { } } -struct Resolver<'a>(&'a[&'static dyn Function], bool); +struct Resolver<'a> { + host_functions: &'a[&'static dyn Function], + enable_stub: bool, +} impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { fn resolve_func(&self, name: &str, signature: &wasmi::Signature) -> std::result::Result { let signature = sp_wasm_interface::Signature::from(signature); - eprintln!("resolve: {}", name); - for (function_index, function) in self.0.iter().enumerate() { + for (function_index, function) in self.host_functions.iter().enumerate() { if name == function.name() { if signature == function.signature() { return Ok( @@ -299,16 +304,11 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { } } - if self.1 { - eprintln!("Could not find function {}. The existing functions are: {}", - name, - self.0.iter() - .map(|x| - x.name()).collect::>().join(",")); + if self.enable_stub { + trace!("Could not find function {}, a stub will be provided instead.", name); - Ok( - wasmi::FuncInstance::alloc_host(signature.into(), self.0.len()), - ) + // NOTE: provide purposedly an invalid index of the function + Ok(wasmi::FuncInstance::alloc_host(signature.into(), self.host_functions.len())) } else { Err(wasmi::Error::Instantiation( format!("Export {} not found", name), @@ -329,7 +329,7 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { .map_err(wasmi::Trap::from) .map(|v| v.map(Into::into)) } else if self.enable_stub { - panic!("function does not exist"); + panic!("function {} does not exist", self.method); } else { Err(Error::from(format!("Could not find host function with index: {}", index)).into()) } @@ -379,7 +379,7 @@ fn call_in_wasm_module( let heap_base = get_heap_base(module_instance)?; let mut fec = FunctionExecutor::new( - memory.clone(), heap_base, table, host_functions, enable_stub)?; + memory.clone(), heap_base, table, host_functions, enable_stub, method)?; // Write the call data let offset = fec.allocate_memory(data.len() as u32)?; @@ -418,7 +418,10 @@ fn instantiate_module( host_functions: &[&'static dyn Function], enable_stub: bool, ) -> Result { - let resolver = Resolver(host_functions, enable_stub); + let resolver = Resolver { + host_functions, + enable_stub, + }; // start module instantiation. Don't run 'start' function yet. let intermediate_instance = ModuleInstance::new( module, From cdd65eecbb3639663d18db4ec961f82e432b85e7 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 12:45:25 +0100 Subject: [PATCH 06/41] WIP --- client/executor/src/integration_tests/mod.rs | 8 +++--- client/executor/wasmi/src/lib.rs | 30 ++++++++++++++------ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index e9f1d367692a7..fdc4faf0ee904 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -90,7 +90,7 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) { #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "function test_calling_missing_external does not exist")] +#[should_panic(expected = "functions do not exist: missing_external, yet_another_missing_external")] fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -103,12 +103,12 @@ fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod &mut ext, &test_code[..], 8, - ); + ).unwrap(); } #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "function test_calling_yet_another_missing_external does not exist")] +#[should_panic(expected = "functions do not exist: missing_external, yet_another_missing_external")] fn call_yet_another_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -121,7 +121,7 @@ fn call_yet_another_not_existing_function_with_stub_enabled(wasm_method: WasmExe &mut ext, &test_code[..], 8, - ); + ).unwrap(); } #[test_case(WasmExecutionMethod::Interpreted)] diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 33ebfa041efdd..e7d02a7d75f65 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -22,6 +22,7 @@ use sc_executor_common::{ allocator, }; use std::{str, mem}; +use std::cell::RefCell; use wasmi::{ Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, memory_units::Pages, RuntimeValue::{I32, I64, self}, @@ -43,7 +44,7 @@ struct FunctionExecutor<'a> { table: Option, host_functions: &'a [&'static dyn Function], enable_stub: bool, - method: &'a str, + missing_functions: &'a Vec, } impl<'a> FunctionExecutor<'a> { @@ -53,7 +54,7 @@ impl<'a> FunctionExecutor<'a> { t: Option, host_functions: &'a [&'static dyn Function], enable_stub: bool, - method: &'a str, + missing_functions: &'a Vec, ) -> Result { Ok(FunctionExecutor { sandbox_store: sandbox::Store::new(), @@ -62,7 +63,7 @@ impl<'a> FunctionExecutor<'a> { table: t, host_functions, enable_stub, - method, + missing_functions, }) } } @@ -278,6 +279,7 @@ impl<'a> Sandbox for FunctionExecutor<'a> { struct Resolver<'a> { host_functions: &'a[&'static dyn Function], enable_stub: bool, + missing_functions: RefCell>, } impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { @@ -306,6 +308,7 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { if self.enable_stub { trace!("Could not find function {}, a stub will be provided instead.", name); + self.missing_functions.borrow_mut().push(name.to_string()); // NOTE: provide purposedly an invalid index of the function Ok(wasmi::FuncInstance::alloc_host(signature.into(), self.host_functions.len())) @@ -329,7 +332,9 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { .map_err(wasmi::Trap::from) .map(|v| v.map(Into::into)) } else if self.enable_stub { - panic!("function {} does not exist", self.method); + Err(Error::from( + format!("functions do not exist: {}", self.missing_functions.join(", ")) + ).into()) } else { Err(Error::from(format!("Could not find host function with index: {}", index)).into()) } @@ -369,6 +374,7 @@ fn call_in_wasm_module( data: &[u8], host_functions: &[&'static dyn Function], enable_stub: bool, + missing_functions: &Vec, ) -> Result, Error> { // extract a reference to a linear memory, optional reference to a table // and then initialize FunctionExecutor. @@ -379,7 +385,7 @@ fn call_in_wasm_module( let heap_base = get_heap_base(module_instance)?; let mut fec = FunctionExecutor::new( - memory.clone(), heap_base, table, host_functions, enable_stub, method)?; + memory.clone(), heap_base, table, host_functions, enable_stub, missing_functions)?; // Write the call data let offset = fec.allocate_memory(data.len() as u32)?; @@ -417,10 +423,11 @@ fn instantiate_module( module: &Module, host_functions: &[&'static dyn Function], enable_stub: bool, -) -> Result { +) -> Result<(ModuleRef, Vec), Error> { let resolver = Resolver { host_functions, enable_stub, + missing_functions: RefCell::new(Vec::new()), }; // start module instantiation. Don't run 'start' function yet. let intermediate_instance = ModuleInstance::new( @@ -439,7 +446,7 @@ fn instantiate_module( // Runtime is not allowed to have the `start` function. Err(Error::RuntimeHasStartFn) } else { - Ok(intermediate_instance.assert_no_start()) + Ok((intermediate_instance.assert_no_start(), resolver.missing_functions.into_inner())) } } @@ -561,6 +568,8 @@ pub struct WasmiRuntime { host_functions: Vec<&'static dyn Function>, /// Enable STUB for function called that are missing enable_stub: bool, + /// List of missing functions detected during function resolution + missing_functions: Vec, } impl WasmRuntime for WasmiRuntime { @@ -587,7 +596,8 @@ impl WasmRuntime for WasmiRuntime { e })?; call_in_wasm_module( - ext, &self.instance, method, data, &self.host_functions, self.enable_stub) + ext, &self.instance, method, data, &self.host_functions, self.enable_stub, + &self.missing_functions) } } @@ -606,7 +616,8 @@ pub fn create_instance( let data_segments = extract_data_segments(&code)?; // Instantiate this module. - let instance = instantiate_module(heap_pages as usize, &module, &host_functions, enable_stub) + let (instance, missing_functions) = instantiate_module( + heap_pages as usize, &module, &host_functions, enable_stub) .map_err(|e| WasmError::Instantiation(e.to_string()))?; // Take state snapshot before executing anything. @@ -623,6 +634,7 @@ pub fn create_instance( state_snapshot, host_functions, enable_stub, + missing_functions, }) } From 935f976cca92dd4f6605f04baf11024ee1e6b8ef Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 12:54:52 +0100 Subject: [PATCH 07/41] Update client/executor/src/integration_tests/mod.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/src/integration_tests/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index fdc4faf0ee904..6aa515c199cc7 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -96,7 +96,7 @@ fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod let mut ext = ext.ext(); let test_code = WASM_BINARY; - let _output = call_in_wasm_with_stub( + call_in_wasm_with_stub( "test_calling_missing_external", &[], wasm_method, From 9ec344c539c09a780777fb4bdc1129e6398a5f2d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 12:55:00 +0100 Subject: [PATCH 08/41] Update client/executor/src/integration_tests/mod.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/src/integration_tests/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 6aa515c199cc7..aa5e6c7804c3d 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -114,7 +114,7 @@ fn call_yet_another_not_existing_function_with_stub_enabled(wasm_method: WasmExe let mut ext = ext.ext(); let test_code = WASM_BINARY; - let _output = call_in_wasm_with_stub( + call_in_wasm_with_stub( "test_calling_yet_another_missing_external", &[], wasm_method, From 5f86a84dfd660183be732eb4794658fb98a7ac17 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 13:07:52 +0100 Subject: [PATCH 09/41] WIP --- client/executor/wasmi/src/lib.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index e7d02a7d75f65..d6d7de6b2bcaf 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -596,8 +596,14 @@ impl WasmRuntime for WasmiRuntime { e })?; call_in_wasm_module( - ext, &self.instance, method, data, &self.host_functions, self.enable_stub, - &self.missing_functions) + ext, + &self.instance, + method, + data, + &self.host_functions, + self.enable_stub, + &self.missing_functions, + ) } } From 335038b383c8c2d56597ab3d2e807f2179813920 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 13:38:36 +0100 Subject: [PATCH 10/41] WIP --- client/executor/src/integration_tests/mod.rs | 4 +-- client/executor/wasmi/src/lib.rs | 27 +++++++++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index aa5e6c7804c3d..c663c78ec51cf 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -90,7 +90,7 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) { #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "functions do not exist: missing_external, yet_another_missing_external")] +#[should_panic(expected = "function missing_external do not exist")] fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -108,7 +108,7 @@ fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "functions do not exist: missing_external, yet_another_missing_external")] +#[should_panic(expected = "function yet_another_missing_external do not exist")] fn call_yet_another_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index d6d7de6b2bcaf..a434cb3c3bcfa 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -280,6 +280,18 @@ struct Resolver<'a> { host_functions: &'a[&'static dyn Function], enable_stub: bool, missing_functions: RefCell>, + missing_function_id: RefCell, +} + +impl<'a> Resolver<'a> { + fn new(host_functions: &'a[&'static dyn Function], enable_stub: bool) -> Resolver<'a> { + Resolver { + host_functions, + enable_stub, + missing_functions: RefCell::new(Vec::new()), + missing_function_id: RefCell::new(host_functions.len()), + } + } } impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { @@ -309,9 +321,11 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { if self.enable_stub { trace!("Could not find function {}, a stub will be provided instead.", name); self.missing_functions.borrow_mut().push(name.to_string()); + let id = self.missing_function_id.borrow().clone(); + *self.missing_function_id.borrow_mut() += 1; // NOTE: provide purposedly an invalid index of the function - Ok(wasmi::FuncInstance::alloc_host(signature.into(), self.host_functions.len())) + Ok(wasmi::FuncInstance::alloc_host(signature.into(), id)) } else { Err(wasmi::Error::Instantiation( format!("Export {} not found", name), @@ -333,7 +347,10 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { .map(|v| v.map(Into::into)) } else if self.enable_stub { Err(Error::from( - format!("functions do not exist: {}", self.missing_functions.join(", ")) + format!( + "function {} do not exist", + self.missing_functions[index - self.host_functions.len()], + ) ).into()) } else { Err(Error::from(format!("Could not find host function with index: {}", index)).into()) @@ -424,11 +441,7 @@ fn instantiate_module( host_functions: &[&'static dyn Function], enable_stub: bool, ) -> Result<(ModuleRef, Vec), Error> { - let resolver = Resolver { - host_functions, - enable_stub, - missing_functions: RefCell::new(Vec::new()), - }; + let resolver = Resolver::new(host_functions, enable_stub); // start module instantiation. Don't run 'start' function yet. let intermediate_instance = ModuleInstance::new( module, From 233399499bd5cf097370b01f20bb66812dbdeb91 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 13:46:39 +0100 Subject: [PATCH 11/41] WIP --- client/executor/wasmi/src/lib.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index a434cb3c3bcfa..e97c5605da180 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -23,6 +23,7 @@ use sc_executor_common::{ }; use std::{str, mem}; use std::cell::RefCell; +use std::collections::HashMap; use wasmi::{ Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, memory_units::Pages, RuntimeValue::{I32, I64, self}, @@ -44,7 +45,7 @@ struct FunctionExecutor<'a> { table: Option, host_functions: &'a [&'static dyn Function], enable_stub: bool, - missing_functions: &'a Vec, + missing_functions: &'a HashMap, } impl<'a> FunctionExecutor<'a> { @@ -54,7 +55,7 @@ impl<'a> FunctionExecutor<'a> { t: Option, host_functions: &'a [&'static dyn Function], enable_stub: bool, - missing_functions: &'a Vec, + missing_functions: &'a HashMap, ) -> Result { Ok(FunctionExecutor { sandbox_store: sandbox::Store::new(), @@ -279,7 +280,7 @@ impl<'a> Sandbox for FunctionExecutor<'a> { struct Resolver<'a> { host_functions: &'a[&'static dyn Function], enable_stub: bool, - missing_functions: RefCell>, + missing_functions: RefCell>, missing_function_id: RefCell, } @@ -288,7 +289,7 @@ impl<'a> Resolver<'a> { Resolver { host_functions, enable_stub, - missing_functions: RefCell::new(Vec::new()), + missing_functions: RefCell::new(HashMap::new()), missing_function_id: RefCell::new(host_functions.len()), } } @@ -320,8 +321,8 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { if self.enable_stub { trace!("Could not find function {}, a stub will be provided instead.", name); - self.missing_functions.borrow_mut().push(name.to_string()); let id = self.missing_function_id.borrow().clone(); + self.missing_functions.borrow_mut().insert(id, name.to_string()); *self.missing_function_id.borrow_mut() += 1; // NOTE: provide purposedly an invalid index of the function @@ -347,10 +348,7 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { .map(|v| v.map(Into::into)) } else if self.enable_stub { Err(Error::from( - format!( - "function {} do not exist", - self.missing_functions[index - self.host_functions.len()], - ) + format!("function {} does not exist", self.missing_functions[&index]) ).into()) } else { Err(Error::from(format!("Could not find host function with index: {}", index)).into()) @@ -391,7 +389,7 @@ fn call_in_wasm_module( data: &[u8], host_functions: &[&'static dyn Function], enable_stub: bool, - missing_functions: &Vec, + missing_functions: &HashMap, ) -> Result, Error> { // extract a reference to a linear memory, optional reference to a table // and then initialize FunctionExecutor. @@ -440,7 +438,7 @@ fn instantiate_module( module: &Module, host_functions: &[&'static dyn Function], enable_stub: bool, -) -> Result<(ModuleRef, Vec), Error> { +) -> Result<(ModuleRef, HashMap), Error> { let resolver = Resolver::new(host_functions, enable_stub); // start module instantiation. Don't run 'start' function yet. let intermediate_instance = ModuleInstance::new( @@ -582,7 +580,7 @@ pub struct WasmiRuntime { /// Enable STUB for function called that are missing enable_stub: bool, /// List of missing functions detected during function resolution - missing_functions: Vec, + missing_functions: HashMap, } impl WasmRuntime for WasmiRuntime { From 0ef27467f6799c68c2d8d88da5def3f6e7171efb Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 14:06:03 +0100 Subject: [PATCH 12/41] WIP --- client/executor/src/integration_tests/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index c663c78ec51cf..3a351bf060d2b 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -90,7 +90,7 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) { #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "function missing_external do not exist")] +#[should_panic(expected = "function missing_external does not exist")] fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); @@ -108,7 +108,7 @@ fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "function yet_another_missing_external do not exist")] +#[should_panic(expected = "function yet_another_missing_external does not exist")] fn call_yet_another_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); From 137497930383b6ae2c4187448fa209542738a049 Mon Sep 17 00:00:00 2001 From: Sergei Shulepov Date: Mon, 6 Jan 2020 14:47:41 +0100 Subject: [PATCH 13/41] Use resolver approach --- client/executor/wasmtime/src/runtime.rs | 168 +++++++++++++++--------- 1 file changed, 103 insertions(+), 65 deletions(-) diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 9395d0049cc2d..32da96e387173 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -40,15 +40,18 @@ use cranelift_frontend::FunctionBuilderContext; use cranelift_wasm::DefinedFuncIndex; use wasmtime_environ::{Module, translate_signature}; use wasmtime_jit::{ - ActionOutcome, CodeMemory, CompilationStrategy, CompiledModule, Compiler, Context, RuntimeValue, + invoke, ActionOutcome, CodeMemory, CompilationStrategy, CompiledModule, Compiler, RuntimeValue, + Resolver, }; use wasmtime_runtime::{Export, Imports, InstanceHandle, VMFunctionBody}; /// A `WasmRuntime` implementation using the Wasmtime JIT to compile the runtime module to native /// and execute the compiled code. pub struct WasmtimeRuntime { + compiler: Compiler, module: CompiledModule, - context: Context, + global_exports: Rc>>>, + env_instance: InstanceHandle, max_heap_pages: Option, heap_pages: u32, /// The host functions registered for this instance. @@ -72,7 +75,9 @@ impl WasmRuntime for WasmtimeRuntime { fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result> { call_method( - &mut self.context, + &mut self.compiler, + &mut self.env_instance, + Rc::clone(&self.global_exports), &mut self.module, ext, method, @@ -82,6 +87,19 @@ impl WasmRuntime for WasmtimeRuntime { } } +struct RuntimeInterfaceResolver<'a> { + env_instance: &'a mut InstanceHandle, +} + +impl<'a> Resolver for RuntimeInterfaceResolver<'a> { + fn resolve(&mut self, module: &str, field: &str) -> Option { + match module { + "env" => self.env_instance.lookup(field), + _ => None, + } + } +} + /// Create a new `WasmtimeRuntime` given the code. This function performs translation from Wasm to /// machine code, which can be computationally heavy. pub fn create_instance( @@ -89,7 +107,22 @@ pub fn create_instance( heap_pages: u64, host_functions: Vec<&'static dyn Function>, ) -> std::result::Result { - let (compiled_module, context) = create_compiled_unit(code, &host_functions)?; + let global_exports = Rc::new(RefCell::new(HashMap::new())); + + let compiler = new_compiler(CompilationStrategy::Cranelift)?; + let mut env_instance = + instantiate_env_module(Rc::clone(&global_exports), compiler, &host_functions)?; + + let mut compiler = new_compiler(CompilationStrategy::Cranelift)?; + let compiled_module = create_compiled_unit( + &mut compiler, + code, + &mut RuntimeInterfaceResolver { + env_instance: &mut env_instance, + }, + Rc::clone(&global_exports), + &host_functions, + )?; // Inspect the module for the min and max memory sizes. let (min_memory_size, max_memory_size) = { @@ -98,53 +131,47 @@ pub fn create_instance( Some(wasmtime_environ::Export::Memory(memory_index)) => *memory_index, _ => return Err(WasmError::InvalidMemory), }; - let memory_plan = module.memory_plans.get(memory_index) + let memory_plan = module + .memory_plans + .get(memory_index) .expect("memory_index is retrieved from the module's exports map; qed"); (memory_plan.memory.minimum, memory_plan.memory.maximum) }; // Check that heap_pages is within the allowed range. let max_heap_pages = max_memory_size.map(|max| max.saturating_sub(min_memory_size)); - let heap_pages = heap_pages_valid(heap_pages, max_heap_pages) - .ok_or_else(|| WasmError::InvalidHeapPages)?; + let heap_pages = + heap_pages_valid(heap_pages, max_heap_pages).ok_or_else(|| WasmError::InvalidHeapPages)?; Ok(WasmtimeRuntime { + compiler, module: compiled_module, - context, max_heap_pages, heap_pages, host_functions, + global_exports, + env_instance, }) } fn create_compiled_unit( + compiler: &mut Compiler, code: &[u8], + resolver: &mut dyn Resolver, + global_exports: Rc>>>, host_functions: &[&'static dyn Function], -) -> std::result::Result<(CompiledModule, Context), WasmError> { - let compilation_strategy = CompilationStrategy::Cranelift; - - let compiler = new_compiler(compilation_strategy)?; - let mut context = Context::new(Box::new(compiler)); - - // Enable/disable producing of debug info. - context.set_debug_info(false); - - // Instantiate and link the env module. - let global_exports = context.get_global_exports(); - let compiler = new_compiler(compilation_strategy)?; - let env_module = instantiate_env_module(global_exports, compiler, host_functions)?; - context.name_instance("env".to_owned(), env_module); - - // Compile the wasm module. - let module = context.compile_module(&code) +) -> std::result::Result { + let debug_info = false; + let module = CompiledModule::new(compiler, code, resolver, global_exports, debug_info) .map_err(|e| WasmError::Other(format!("module compile error: {}", e)))?; - - Ok((module, context)) + Ok(module) } /// Call a function inside a precompiled Wasm module. fn call_method( - context: &mut Context, + compiler: &mut Compiler, + env_instance: &mut InstanceHandle, + global_exports: Rc>>>, module: &mut CompiledModule, ext: &mut dyn Externalities, method: &str, @@ -155,9 +182,10 @@ fn call_method( // // The global exports mechanism is temporary in Wasmtime and expected to be removed. // https://github.com/CraneStation/wasmtime/issues/332 - clear_globals(&mut *context.get_global_exports().borrow_mut()); + clear_globals(&mut *global_exports.borrow_mut()); - let mut instance = module.instantiate() + let mut instance = module + .instantiate() .map_err(|e| Error::Other(e.to_string()))?; // Ideally there would be a way to set the heap pages during instantiation rather than @@ -169,27 +197,31 @@ fn call_method( // Initialize the function executor state. let heap_base = get_heap_base(&instance)?; let executor_state = FunctionExecutorState::new(heap_base); - reset_env_state_and_take_trap(context, Some(executor_state))?; + reset_env_state_and_take_trap(env_instance, Some(executor_state))?; // Write the input data into guest memory. - let (data_ptr, data_len) = inject_input_data(context, &mut instance, data)?; - let args = [RuntimeValue::I32(u32::from(data_ptr) as i32), RuntimeValue::I32(data_len as i32)]; + let (data_ptr, data_len) = inject_input_data(env_instance, &mut instance, data)?; + let args = [ + RuntimeValue::I32(u32::from(data_ptr) as i32), + RuntimeValue::I32(data_len as i32), + ]; // Invoke the function in the runtime. let outcome = sp_externalities::set_and_run_with_externalities(ext, || { - context - .invoke(&mut instance, method, &args[..]) + invoke(compiler, &mut instance, method, &args[..]) .map_err(|e| Error::Other(format!("error calling runtime: {}", e))) })?; - let trap_error = reset_env_state_and_take_trap(context, None)?; + let trap_error = reset_env_state_and_take_trap(env_instance, None)?; let (output_ptr, output_len) = match outcome { ActionOutcome::Returned { values } => match values.as_slice() { [RuntimeValue::I64(retval)] => unpack_ptr_and_len(*retval as u64), _ => return Err(Error::InvalidReturn), + }, + ActionOutcome::Trapped { message } => { + return Err( + trap_error.unwrap_or_else(|| format!("Wasm execution trapped: {}", message).into()) + ) } - ActionOutcome::Trapped { message } => return Err(trap_error.unwrap_or_else( - || format!("Wasm execution trapped: {}", message).into() - )), }; // Read the output data from guest memory. @@ -204,8 +236,7 @@ fn instantiate_env_module( global_exports: Rc>>>, compiler: Compiler, host_functions: &[&'static dyn Function], -) -> std::result::Result -{ +) -> std::result::Result { let isa = target_isa()?; let pointer_type = isa.pointer_type(); let call_conv = isa.default_call_conv(); @@ -218,13 +249,14 @@ fn instantiate_env_module( for function in host_functions { let sig = translate_signature( cranelift_ir_signature(function.signature(), &call_conv), - pointer_type + pointer_type, ); let sig_id = module.signatures.push(sig.clone()); let func_id = module.functions.push(sig_id); - module - .exports - .insert(function.name().to_string(), wasmtime_environ::Export::Function(func_id)); + module.exports.insert( + function.name().to_string(), + wasmtime_environ::Export::Function(func_id), + ); let trampoline = make_trampoline( isa.as_ref(), @@ -281,19 +313,21 @@ fn grow_memory(instance: &mut InstanceHandle, pages: u32) -> Result<()> { // - The definition pointer is returned by a lookup on a valid instance let memory_index = unsafe { match instance.lookup_immutable("memory") { - Some(Export::Memory { definition, vmctx: _, memory: _ }) => - instance.memory_index(&*definition), + Some(Export::Memory { + definition, + vmctx: _, + memory: _, + }) => instance.memory_index(&*definition), _ => return Err(Error::InvalidMemoryReference), } }; - instance.memory_grow(memory_index, pages) + instance + .memory_grow(memory_index, pages) .map(|_| ()) .ok_or_else(|| "requested heap_pages would exceed maximum memory size".into()) } -fn get_env_state(context: &mut Context) -> Result<&mut EnvState> { - let env_instance = context.get_instance("env") - .map_err(|err| format!("cannot find \"env\" module: {}", err))?; +fn get_env_state(env_instance: &mut InstanceHandle) -> Result<&mut EnvState> { env_instance .host_state() .downcast_mut::() @@ -301,22 +335,22 @@ fn get_env_state(context: &mut Context) -> Result<&mut EnvState> { } fn reset_env_state_and_take_trap( - context: &mut Context, + env_instance: &mut InstanceHandle, executor_state: Option, -) -> Result> -{ - let env_state = get_env_state(context)?; +) -> Result> { + let env_state = get_env_state(env_instance)?; env_state.executor_state = executor_state; Ok(env_state.take_trap()) } fn inject_input_data( - context: &mut Context, + env_instance: &mut InstanceHandle, instance: &mut InstanceHandle, data: &[u8], ) -> Result<(Pointer, WordSize)> { - let env_state = get_env_state(context)?; - let executor_state = env_state.executor_state + let env_state = get_env_state(env_instance)?; + let executor_state = env_state + .executor_state .as_mut() .ok_or_else(|| "cannot get \"env\" module executor state")?; @@ -333,7 +367,11 @@ fn get_memory_mut(instance: &mut InstanceHandle) -> Result<&mut [u8]> { // This is safe to wrap in an unsafe block as: // - The definition pointer is returned by a lookup on a valid instance and thus points to // a valid memory definition - Some(Export::Memory { definition, vmctx: _, memory: _ }) => unsafe { + Some(Export::Memory { + definition, + vmctx: _, + memory: _, + }) => unsafe { Ok(std::slice::from_raw_parts_mut( (*definition).base, (*definition).current_length, @@ -350,9 +388,11 @@ fn get_heap_base(instance: &InstanceHandle) -> Result { // - The defined value is checked to be an I32, which can be read safely as a u32 unsafe { match instance.lookup_immutable("__heap_base") { - Some(Export::Global { definition, vmctx: _, global }) - if global.ty == ir::types::I32 => - Ok(*(*definition).as_u32()), + Some(Export::Global { + definition, + vmctx: _, + global, + }) if global.ty == ir::types::I32 => Ok(*(*definition).as_u32()), _ => return Err(Error::HeapBaseNotFoundOrInvalid), } } @@ -360,9 +400,7 @@ fn get_heap_base(instance: &InstanceHandle) -> Result { /// Checks whether the heap_pages parameter is within the valid range and converts it to a u32. /// Returns None if heaps_pages in not in range. -fn heap_pages_valid(heap_pages: u64, max_heap_pages: Option) - -> Option -{ +fn heap_pages_valid(heap_pages: u64, max_heap_pages: Option) -> Option { let heap_pages = u32::try_from(heap_pages).ok()?; if let Some(max_heap_pages) = max_heap_pages { if heap_pages > max_heap_pages { From 79f4a2a1e5deb281ad11373a6ae6cb5b2e76b295 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Tue, 7 Jan 2020 17:08:19 +0100 Subject: [PATCH 14/41] wasmtime --- client/executor/src/wasm_runtime.rs | 2 +- client/executor/wasmtime/src/runtime.rs | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 18d53a7745333..78b83d94a3db2 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -199,7 +199,7 @@ pub fn create_wasm_runtime_with_code( .map(|runtime| -> Box { Box::new(runtime) }), #[cfg(feature = "wasmtime")] WasmExecutionMethod::Compiled => - sc_executor_wasmtime::create_instance(code, heap_pages, host_functions) + sc_executor_wasmtime::create_instance(code, heap_pages, host_functions, enable_stub) .map(|runtime| -> Box { Box::new(runtime) }), } } diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 32da96e387173..9a8cfb4a9e69e 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -56,6 +56,10 @@ pub struct WasmtimeRuntime { heap_pages: u32, /// The host functions registered for this instance. host_functions: Vec<&'static dyn Function>, + /// Enable STUB for function called that are missing + enable_stub: bool, + /// List of missing functions detected during function resolution + missing_functions: HashMap, } impl WasmRuntime for WasmtimeRuntime { @@ -83,6 +87,8 @@ impl WasmRuntime for WasmtimeRuntime { method, data, self.heap_pages, + self.enable_stub, + &self.missing_functions, ) } } @@ -106,6 +112,7 @@ pub fn create_instance( code: &[u8], heap_pages: u64, host_functions: Vec<&'static dyn Function>, + enable_stub: bool, ) -> std::result::Result { let global_exports = Rc::new(RefCell::new(HashMap::new())); @@ -114,6 +121,7 @@ pub fn create_instance( instantiate_env_module(Rc::clone(&global_exports), compiler, &host_functions)?; let mut compiler = new_compiler(CompilationStrategy::Cranelift)?; + // let (compiled_module, context, missing_functions) = create_compiled_unit(code, &host_functions, enable_stub)?; let compiled_module = create_compiled_unit( &mut compiler, code, @@ -151,6 +159,8 @@ pub fn create_instance( host_functions, global_exports, env_instance, + enable_stub, + missing_functions, }) } @@ -160,7 +170,8 @@ fn create_compiled_unit( resolver: &mut dyn Resolver, global_exports: Rc>>>, host_functions: &[&'static dyn Function], -) -> std::result::Result { + enable_stub: bool, +) -> std::result::Result<(CompiledModule, HashMap), WasmError> { let debug_info = false; let module = CompiledModule::new(compiler, code, resolver, global_exports, debug_info) .map_err(|e| WasmError::Other(format!("module compile error: {}", e)))?; @@ -177,6 +188,8 @@ fn call_method( method: &str, data: &[u8], heap_pages: u32, + enable_stub: bool, + missing_functions: &HashMap, ) -> Result> { // Old exports get clobbered in `InstanceHandle::new` if we don't explicitly remove them first. // From 997bb60d2012465c4a6f12f69e287a693e4e940d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 8 Jan 2020 11:58:19 +0100 Subject: [PATCH 15/41] Revert "wasmtime" This reverts commit 79f4a2a1e5deb281ad11373a6ae6cb5b2e76b295. --- client/executor/src/wasm_runtime.rs | 2 +- client/executor/wasmtime/src/runtime.rs | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 78b83d94a3db2..18d53a7745333 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -199,7 +199,7 @@ pub fn create_wasm_runtime_with_code( .map(|runtime| -> Box { Box::new(runtime) }), #[cfg(feature = "wasmtime")] WasmExecutionMethod::Compiled => - sc_executor_wasmtime::create_instance(code, heap_pages, host_functions, enable_stub) + sc_executor_wasmtime::create_instance(code, heap_pages, host_functions) .map(|runtime| -> Box { Box::new(runtime) }), } } diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 9a8cfb4a9e69e..32da96e387173 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -56,10 +56,6 @@ pub struct WasmtimeRuntime { heap_pages: u32, /// The host functions registered for this instance. host_functions: Vec<&'static dyn Function>, - /// Enable STUB for function called that are missing - enable_stub: bool, - /// List of missing functions detected during function resolution - missing_functions: HashMap, } impl WasmRuntime for WasmtimeRuntime { @@ -87,8 +83,6 @@ impl WasmRuntime for WasmtimeRuntime { method, data, self.heap_pages, - self.enable_stub, - &self.missing_functions, ) } } @@ -112,7 +106,6 @@ pub fn create_instance( code: &[u8], heap_pages: u64, host_functions: Vec<&'static dyn Function>, - enable_stub: bool, ) -> std::result::Result { let global_exports = Rc::new(RefCell::new(HashMap::new())); @@ -121,7 +114,6 @@ pub fn create_instance( instantiate_env_module(Rc::clone(&global_exports), compiler, &host_functions)?; let mut compiler = new_compiler(CompilationStrategy::Cranelift)?; - // let (compiled_module, context, missing_functions) = create_compiled_unit(code, &host_functions, enable_stub)?; let compiled_module = create_compiled_unit( &mut compiler, code, @@ -159,8 +151,6 @@ pub fn create_instance( host_functions, global_exports, env_instance, - enable_stub, - missing_functions, }) } @@ -170,8 +160,7 @@ fn create_compiled_unit( resolver: &mut dyn Resolver, global_exports: Rc>>>, host_functions: &[&'static dyn Function], - enable_stub: bool, -) -> std::result::Result<(CompiledModule, HashMap), WasmError> { +) -> std::result::Result { let debug_info = false; let module = CompiledModule::new(compiler, code, resolver, global_exports, debug_info) .map_err(|e| WasmError::Other(format!("module compile error: {}", e)))?; @@ -188,8 +177,6 @@ fn call_method( method: &str, data: &[u8], heap_pages: u32, - enable_stub: bool, - missing_functions: &HashMap, ) -> Result> { // Old exports get clobbered in `InstanceHandle::new` if we don't explicitly remove them first. // From f7109d13d7532fd8b6eb94906aaece09ba2b274b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 8 Jan 2020 11:58:27 +0100 Subject: [PATCH 16/41] Revert "Use resolver approach" This reverts commit 137497930383b6ae2c4187448fa209542738a049. --- client/executor/wasmtime/src/runtime.rs | 168 +++++++++--------------- 1 file changed, 65 insertions(+), 103 deletions(-) diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 32da96e387173..9395d0049cc2d 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -40,18 +40,15 @@ use cranelift_frontend::FunctionBuilderContext; use cranelift_wasm::DefinedFuncIndex; use wasmtime_environ::{Module, translate_signature}; use wasmtime_jit::{ - invoke, ActionOutcome, CodeMemory, CompilationStrategy, CompiledModule, Compiler, RuntimeValue, - Resolver, + ActionOutcome, CodeMemory, CompilationStrategy, CompiledModule, Compiler, Context, RuntimeValue, }; use wasmtime_runtime::{Export, Imports, InstanceHandle, VMFunctionBody}; /// A `WasmRuntime` implementation using the Wasmtime JIT to compile the runtime module to native /// and execute the compiled code. pub struct WasmtimeRuntime { - compiler: Compiler, module: CompiledModule, - global_exports: Rc>>>, - env_instance: InstanceHandle, + context: Context, max_heap_pages: Option, heap_pages: u32, /// The host functions registered for this instance. @@ -75,9 +72,7 @@ impl WasmRuntime for WasmtimeRuntime { fn call(&mut self, ext: &mut dyn Externalities, method: &str, data: &[u8]) -> Result> { call_method( - &mut self.compiler, - &mut self.env_instance, - Rc::clone(&self.global_exports), + &mut self.context, &mut self.module, ext, method, @@ -87,19 +82,6 @@ impl WasmRuntime for WasmtimeRuntime { } } -struct RuntimeInterfaceResolver<'a> { - env_instance: &'a mut InstanceHandle, -} - -impl<'a> Resolver for RuntimeInterfaceResolver<'a> { - fn resolve(&mut self, module: &str, field: &str) -> Option { - match module { - "env" => self.env_instance.lookup(field), - _ => None, - } - } -} - /// Create a new `WasmtimeRuntime` given the code. This function performs translation from Wasm to /// machine code, which can be computationally heavy. pub fn create_instance( @@ -107,22 +89,7 @@ pub fn create_instance( heap_pages: u64, host_functions: Vec<&'static dyn Function>, ) -> std::result::Result { - let global_exports = Rc::new(RefCell::new(HashMap::new())); - - let compiler = new_compiler(CompilationStrategy::Cranelift)?; - let mut env_instance = - instantiate_env_module(Rc::clone(&global_exports), compiler, &host_functions)?; - - let mut compiler = new_compiler(CompilationStrategy::Cranelift)?; - let compiled_module = create_compiled_unit( - &mut compiler, - code, - &mut RuntimeInterfaceResolver { - env_instance: &mut env_instance, - }, - Rc::clone(&global_exports), - &host_functions, - )?; + let (compiled_module, context) = create_compiled_unit(code, &host_functions)?; // Inspect the module for the min and max memory sizes. let (min_memory_size, max_memory_size) = { @@ -131,47 +98,53 @@ pub fn create_instance( Some(wasmtime_environ::Export::Memory(memory_index)) => *memory_index, _ => return Err(WasmError::InvalidMemory), }; - let memory_plan = module - .memory_plans - .get(memory_index) + let memory_plan = module.memory_plans.get(memory_index) .expect("memory_index is retrieved from the module's exports map; qed"); (memory_plan.memory.minimum, memory_plan.memory.maximum) }; // Check that heap_pages is within the allowed range. let max_heap_pages = max_memory_size.map(|max| max.saturating_sub(min_memory_size)); - let heap_pages = - heap_pages_valid(heap_pages, max_heap_pages).ok_or_else(|| WasmError::InvalidHeapPages)?; + let heap_pages = heap_pages_valid(heap_pages, max_heap_pages) + .ok_or_else(|| WasmError::InvalidHeapPages)?; Ok(WasmtimeRuntime { - compiler, module: compiled_module, + context, max_heap_pages, heap_pages, host_functions, - global_exports, - env_instance, }) } fn create_compiled_unit( - compiler: &mut Compiler, code: &[u8], - resolver: &mut dyn Resolver, - global_exports: Rc>>>, host_functions: &[&'static dyn Function], -) -> std::result::Result { - let debug_info = false; - let module = CompiledModule::new(compiler, code, resolver, global_exports, debug_info) +) -> std::result::Result<(CompiledModule, Context), WasmError> { + let compilation_strategy = CompilationStrategy::Cranelift; + + let compiler = new_compiler(compilation_strategy)?; + let mut context = Context::new(Box::new(compiler)); + + // Enable/disable producing of debug info. + context.set_debug_info(false); + + // Instantiate and link the env module. + let global_exports = context.get_global_exports(); + let compiler = new_compiler(compilation_strategy)?; + let env_module = instantiate_env_module(global_exports, compiler, host_functions)?; + context.name_instance("env".to_owned(), env_module); + + // Compile the wasm module. + let module = context.compile_module(&code) .map_err(|e| WasmError::Other(format!("module compile error: {}", e)))?; - Ok(module) + + Ok((module, context)) } /// Call a function inside a precompiled Wasm module. fn call_method( - compiler: &mut Compiler, - env_instance: &mut InstanceHandle, - global_exports: Rc>>>, + context: &mut Context, module: &mut CompiledModule, ext: &mut dyn Externalities, method: &str, @@ -182,10 +155,9 @@ fn call_method( // // The global exports mechanism is temporary in Wasmtime and expected to be removed. // https://github.com/CraneStation/wasmtime/issues/332 - clear_globals(&mut *global_exports.borrow_mut()); + clear_globals(&mut *context.get_global_exports().borrow_mut()); - let mut instance = module - .instantiate() + let mut instance = module.instantiate() .map_err(|e| Error::Other(e.to_string()))?; // Ideally there would be a way to set the heap pages during instantiation rather than @@ -197,31 +169,27 @@ fn call_method( // Initialize the function executor state. let heap_base = get_heap_base(&instance)?; let executor_state = FunctionExecutorState::new(heap_base); - reset_env_state_and_take_trap(env_instance, Some(executor_state))?; + reset_env_state_and_take_trap(context, Some(executor_state))?; // Write the input data into guest memory. - let (data_ptr, data_len) = inject_input_data(env_instance, &mut instance, data)?; - let args = [ - RuntimeValue::I32(u32::from(data_ptr) as i32), - RuntimeValue::I32(data_len as i32), - ]; + let (data_ptr, data_len) = inject_input_data(context, &mut instance, data)?; + let args = [RuntimeValue::I32(u32::from(data_ptr) as i32), RuntimeValue::I32(data_len as i32)]; // Invoke the function in the runtime. let outcome = sp_externalities::set_and_run_with_externalities(ext, || { - invoke(compiler, &mut instance, method, &args[..]) + context + .invoke(&mut instance, method, &args[..]) .map_err(|e| Error::Other(format!("error calling runtime: {}", e))) })?; - let trap_error = reset_env_state_and_take_trap(env_instance, None)?; + let trap_error = reset_env_state_and_take_trap(context, None)?; let (output_ptr, output_len) = match outcome { ActionOutcome::Returned { values } => match values.as_slice() { [RuntimeValue::I64(retval)] => unpack_ptr_and_len(*retval as u64), _ => return Err(Error::InvalidReturn), - }, - ActionOutcome::Trapped { message } => { - return Err( - trap_error.unwrap_or_else(|| format!("Wasm execution trapped: {}", message).into()) - ) } + ActionOutcome::Trapped { message } => return Err(trap_error.unwrap_or_else( + || format!("Wasm execution trapped: {}", message).into() + )), }; // Read the output data from guest memory. @@ -236,7 +204,8 @@ fn instantiate_env_module( global_exports: Rc>>>, compiler: Compiler, host_functions: &[&'static dyn Function], -) -> std::result::Result { +) -> std::result::Result +{ let isa = target_isa()?; let pointer_type = isa.pointer_type(); let call_conv = isa.default_call_conv(); @@ -249,14 +218,13 @@ fn instantiate_env_module( for function in host_functions { let sig = translate_signature( cranelift_ir_signature(function.signature(), &call_conv), - pointer_type, + pointer_type ); let sig_id = module.signatures.push(sig.clone()); let func_id = module.functions.push(sig_id); - module.exports.insert( - function.name().to_string(), - wasmtime_environ::Export::Function(func_id), - ); + module + .exports + .insert(function.name().to_string(), wasmtime_environ::Export::Function(func_id)); let trampoline = make_trampoline( isa.as_ref(), @@ -313,21 +281,19 @@ fn grow_memory(instance: &mut InstanceHandle, pages: u32) -> Result<()> { // - The definition pointer is returned by a lookup on a valid instance let memory_index = unsafe { match instance.lookup_immutable("memory") { - Some(Export::Memory { - definition, - vmctx: _, - memory: _, - }) => instance.memory_index(&*definition), + Some(Export::Memory { definition, vmctx: _, memory: _ }) => + instance.memory_index(&*definition), _ => return Err(Error::InvalidMemoryReference), } }; - instance - .memory_grow(memory_index, pages) + instance.memory_grow(memory_index, pages) .map(|_| ()) .ok_or_else(|| "requested heap_pages would exceed maximum memory size".into()) } -fn get_env_state(env_instance: &mut InstanceHandle) -> Result<&mut EnvState> { +fn get_env_state(context: &mut Context) -> Result<&mut EnvState> { + let env_instance = context.get_instance("env") + .map_err(|err| format!("cannot find \"env\" module: {}", err))?; env_instance .host_state() .downcast_mut::() @@ -335,22 +301,22 @@ fn get_env_state(env_instance: &mut InstanceHandle) -> Result<&mut EnvState> { } fn reset_env_state_and_take_trap( - env_instance: &mut InstanceHandle, + context: &mut Context, executor_state: Option, -) -> Result> { - let env_state = get_env_state(env_instance)?; +) -> Result> +{ + let env_state = get_env_state(context)?; env_state.executor_state = executor_state; Ok(env_state.take_trap()) } fn inject_input_data( - env_instance: &mut InstanceHandle, + context: &mut Context, instance: &mut InstanceHandle, data: &[u8], ) -> Result<(Pointer, WordSize)> { - let env_state = get_env_state(env_instance)?; - let executor_state = env_state - .executor_state + let env_state = get_env_state(context)?; + let executor_state = env_state.executor_state .as_mut() .ok_or_else(|| "cannot get \"env\" module executor state")?; @@ -367,11 +333,7 @@ fn get_memory_mut(instance: &mut InstanceHandle) -> Result<&mut [u8]> { // This is safe to wrap in an unsafe block as: // - The definition pointer is returned by a lookup on a valid instance and thus points to // a valid memory definition - Some(Export::Memory { - definition, - vmctx: _, - memory: _, - }) => unsafe { + Some(Export::Memory { definition, vmctx: _, memory: _ }) => unsafe { Ok(std::slice::from_raw_parts_mut( (*definition).base, (*definition).current_length, @@ -388,11 +350,9 @@ fn get_heap_base(instance: &InstanceHandle) -> Result { // - The defined value is checked to be an I32, which can be read safely as a u32 unsafe { match instance.lookup_immutable("__heap_base") { - Some(Export::Global { - definition, - vmctx: _, - global, - }) if global.ty == ir::types::I32 => Ok(*(*definition).as_u32()), + Some(Export::Global { definition, vmctx: _, global }) + if global.ty == ir::types::I32 => + Ok(*(*definition).as_u32()), _ => return Err(Error::HeapBaseNotFoundOrInvalid), } } @@ -400,7 +360,9 @@ fn get_heap_base(instance: &InstanceHandle) -> Result { /// Checks whether the heap_pages parameter is within the valid range and converts it to a u32. /// Returns None if heaps_pages in not in range. -fn heap_pages_valid(heap_pages: u64, max_heap_pages: Option) -> Option { +fn heap_pages_valid(heap_pages: u64, max_heap_pages: Option) + -> Option +{ let heap_pages = u32::try_from(heap_pages).ok()?; if let Some(max_heap_pages) = max_heap_pages { if heap_pages > max_heap_pages { From c2f0e0d714f2e1a5520a7f3ced97f7d006709fed Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 8 Jan 2020 12:08:51 +0100 Subject: [PATCH 17/41] WIP --- client/executor/src/integration_tests/mod.rs | 47 +++----------------- client/executor/src/lib.rs | 6 +-- client/executor/src/wasm_runtime.rs | 4 +- client/executor/wasmi/src/lib.rs | 34 +++++++------- 4 files changed, 28 insertions(+), 63 deletions(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 3a351bf060d2b..3f685b93a528a 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -39,25 +39,6 @@ fn call_in_wasm( ext: &mut E, code: &[u8], heap_pages: u64, -) -> crate::error::Result> { - crate::call_in_wasm::( - function, - call_data, - execution_method, - ext, - code, - heap_pages, - false, - ) -} - -fn call_in_wasm_with_stub( - function: &str, - call_data: &[u8], - execution_method: WasmExecutionMethod, - ext: &mut E, - code: &[u8], - heap_pages: u64, ) -> crate::error::Result> { crate::call_in_wasm::( function, @@ -91,12 +72,13 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) { #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] #[should_panic(expected = "function missing_external does not exist")] -fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { +#[cfg(not(feature = "wasmtime"))] +fn call_not_existing_function(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); let test_code = WASM_BINARY; - call_in_wasm_with_stub( + call_in_wasm( "test_calling_missing_external", &[], wasm_method, @@ -109,12 +91,13 @@ fn call_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] #[should_panic(expected = "function yet_another_missing_external does not exist")] -fn call_yet_another_not_existing_function_with_stub_enabled(wasm_method: WasmExecutionMethod) { +#[cfg(not(feature = "wasmtime"))] +fn call_yet_another_not_existing_function(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); let mut ext = ext.ext(); let test_code = WASM_BINARY; - call_in_wasm_with_stub( + call_in_wasm( "test_calling_yet_another_missing_external", &[], wasm_method, @@ -124,24 +107,6 @@ fn call_yet_another_not_existing_function_with_stub_enabled(wasm_method: WasmExe ).unwrap(); } -#[test_case(WasmExecutionMethod::Interpreted)] -#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -fn call_not_existing_function_without_stub_enabled(wasm_method: WasmExecutionMethod) { - let mut ext = TestExternalities::default(); - let mut ext = ext.ext(); - let test_code = WASM_BINARY; - - let output = call_in_wasm( - "test_calling_missing_external", - &[], - wasm_method, - &mut ext, - &test_code[..], - 8, - ); - assert!(output.is_err()); -} - #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] fn panicking_should_work(wasm_method: WasmExecutionMethod) { diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs index b9aa04e9c8dff..e8129fb3d09d7 100644 --- a/client/executor/src/lib.rs +++ b/client/executor/src/lib.rs @@ -67,14 +67,14 @@ pub fn call_in_wasm( ext: &mut E, code: &[u8], heap_pages: u64, - enable_stub: bool, + allow_missing_imports: bool, ) -> error::Result> { let mut instance = wasm_runtime::create_wasm_runtime_with_code( execution_method, heap_pages, code, HF::host_functions(), - enable_stub, + allow_missing_imports, )?; instance.call(ext, function, call_data) } @@ -105,7 +105,7 @@ mod tests { &mut ext, &WASM_BINARY, 8, - false, + true, ).unwrap(); assert_eq!(res, vec![0u8; 0]); } diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 18d53a7745333..4ccbd6d6ce638 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -191,11 +191,11 @@ pub fn create_wasm_runtime_with_code( heap_pages: u64, code: &[u8], host_functions: Vec<&'static dyn Function>, - enable_stub: bool, + allow_missing_imports: bool, ) -> Result, WasmError> { match wasm_method { WasmExecutionMethod::Interpreted => - sc_executor_wasmi::create_instance(code, heap_pages, host_functions, enable_stub) + sc_executor_wasmi::create_instance(code, heap_pages, host_functions, allow_missing_imports) .map(|runtime| -> Box { Box::new(runtime) }), #[cfg(feature = "wasmtime")] WasmExecutionMethod::Compiled => diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index e97c5605da180..e8d15e9b89fce 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -44,7 +44,7 @@ struct FunctionExecutor<'a> { memory: MemoryRef, table: Option, host_functions: &'a [&'static dyn Function], - enable_stub: bool, + allow_missing_imports: bool, missing_functions: &'a HashMap, } @@ -54,7 +54,7 @@ impl<'a> FunctionExecutor<'a> { heap_base: u32, t: Option, host_functions: &'a [&'static dyn Function], - enable_stub: bool, + allow_missing_imports: bool, missing_functions: &'a HashMap, ) -> Result { Ok(FunctionExecutor { @@ -63,7 +63,7 @@ impl<'a> FunctionExecutor<'a> { memory: m, table: t, host_functions, - enable_stub, + allow_missing_imports, missing_functions, }) } @@ -279,16 +279,16 @@ impl<'a> Sandbox for FunctionExecutor<'a> { struct Resolver<'a> { host_functions: &'a[&'static dyn Function], - enable_stub: bool, + allow_missing_imports: bool, missing_functions: RefCell>, missing_function_id: RefCell, } impl<'a> Resolver<'a> { - fn new(host_functions: &'a[&'static dyn Function], enable_stub: bool) -> Resolver<'a> { + fn new(host_functions: &'a[&'static dyn Function], allow_missing_imports: bool) -> Resolver<'a> { Resolver { host_functions, - enable_stub, + allow_missing_imports, missing_functions: RefCell::new(HashMap::new()), missing_function_id: RefCell::new(host_functions.len()), } @@ -319,7 +319,7 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { } } - if self.enable_stub { + if self.allow_missing_imports { trace!("Could not find function {}, a stub will be provided instead.", name); let id = self.missing_function_id.borrow().clone(); self.missing_functions.borrow_mut().insert(id, name.to_string()); @@ -346,7 +346,7 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { .map_err(|msg| Error::FunctionExecution(function.name().to_string(), msg)) .map_err(wasmi::Trap::from) .map(|v| v.map(Into::into)) - } else if self.enable_stub { + } else if self.allow_missing_imports { Err(Error::from( format!("function {} does not exist", self.missing_functions[&index]) ).into()) @@ -388,7 +388,7 @@ fn call_in_wasm_module( method: &str, data: &[u8], host_functions: &[&'static dyn Function], - enable_stub: bool, + allow_missing_imports: bool, missing_functions: &HashMap, ) -> Result, Error> { // extract a reference to a linear memory, optional reference to a table @@ -400,7 +400,7 @@ fn call_in_wasm_module( let heap_base = get_heap_base(module_instance)?; let mut fec = FunctionExecutor::new( - memory.clone(), heap_base, table, host_functions, enable_stub, missing_functions)?; + memory.clone(), heap_base, table, host_functions, allow_missing_imports, missing_functions)?; // Write the call data let offset = fec.allocate_memory(data.len() as u32)?; @@ -437,9 +437,9 @@ fn instantiate_module( heap_pages: usize, module: &Module, host_functions: &[&'static dyn Function], - enable_stub: bool, + allow_missing_imports: bool, ) -> Result<(ModuleRef, HashMap), Error> { - let resolver = Resolver::new(host_functions, enable_stub); + let resolver = Resolver::new(host_functions, allow_missing_imports); // start module instantiation. Don't run 'start' function yet. let intermediate_instance = ModuleInstance::new( module, @@ -578,7 +578,7 @@ pub struct WasmiRuntime { /// The host functions registered for this instance. host_functions: Vec<&'static dyn Function>, /// Enable STUB for function called that are missing - enable_stub: bool, + allow_missing_imports: bool, /// List of missing functions detected during function resolution missing_functions: HashMap, } @@ -612,7 +612,7 @@ impl WasmRuntime for WasmiRuntime { method, data, &self.host_functions, - self.enable_stub, + self.allow_missing_imports, &self.missing_functions, ) } @@ -622,7 +622,7 @@ pub fn create_instance( code: &[u8], heap_pages: u64, host_functions: Vec<&'static dyn Function>, - enable_stub: bool, + allow_missing_imports: bool, ) -> Result { let module = Module::from_buffer(&code).map_err(|_| WasmError::InvalidModule)?; @@ -634,7 +634,7 @@ pub fn create_instance( // Instantiate this module. let (instance, missing_functions) = instantiate_module( - heap_pages as usize, &module, &host_functions, enable_stub) + heap_pages as usize, &module, &host_functions, allow_missing_imports) .map_err(|e| WasmError::Instantiation(e.to_string()))?; // Take state snapshot before executing anything. @@ -650,7 +650,7 @@ pub fn create_instance( instance, state_snapshot, host_functions, - enable_stub, + allow_missing_imports, missing_functions, }) } From 797bfb61c62f06a3323e42fca1b85e4d7aa37b1a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 8 Jan 2020 12:18:35 +0100 Subject: [PATCH 18/41] WIP --- client/executor/runtime-test/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index a8d329cdd9607..22694407b67ab 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -20,12 +20,15 @@ use sp_core::{ed25519, sr25519}; extern "C" { #[allow(dead_code)] + #[cfg(not(feature = "wasmtime"))] fn missing_external(); #[allow(dead_code)] + #[cfg(not(feature = "wasmtime"))] fn yet_another_missing_external(); } +#[cfg(not(feature = "wasmtime"))] sp_core::wasm_export_functions! { fn test_calling_missing_external() { unsafe { missing_external() } @@ -34,7 +37,9 @@ sp_core::wasm_export_functions! { fn test_calling_yet_another_missing_external() { unsafe { yet_another_missing_external() } } +} +sp_core::wasm_export_functions! { fn test_data_in(input: Vec) -> Vec { print("set_storage"); storage::set(b"input", &input); From d889cf775384d78192946cd749b67f5c3c48b964 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 8 Jan 2020 12:36:24 +0100 Subject: [PATCH 19/41] WIP --- client/executor/wasmi/src/lib.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index e8d15e9b89fce..1b9f06c59d0c0 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -23,7 +23,6 @@ use sc_executor_common::{ }; use std::{str, mem}; use std::cell::RefCell; -use std::collections::HashMap; use wasmi::{ Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, memory_units::Pages, RuntimeValue::{I32, I64, self}, @@ -45,7 +44,7 @@ struct FunctionExecutor<'a> { table: Option, host_functions: &'a [&'static dyn Function], allow_missing_imports: bool, - missing_functions: &'a HashMap, + missing_functions: &'a Vec, } impl<'a> FunctionExecutor<'a> { @@ -55,7 +54,7 @@ impl<'a> FunctionExecutor<'a> { t: Option, host_functions: &'a [&'static dyn Function], allow_missing_imports: bool, - missing_functions: &'a HashMap, + missing_functions: &'a Vec, ) -> Result { Ok(FunctionExecutor { sandbox_store: sandbox::Store::new(), @@ -280,7 +279,7 @@ impl<'a> Sandbox for FunctionExecutor<'a> { struct Resolver<'a> { host_functions: &'a[&'static dyn Function], allow_missing_imports: bool, - missing_functions: RefCell>, + missing_functions: RefCell>, missing_function_id: RefCell, } @@ -289,7 +288,7 @@ impl<'a> Resolver<'a> { Resolver { host_functions, allow_missing_imports, - missing_functions: RefCell::new(HashMap::new()), + missing_functions: RefCell::new(Vec::new()), missing_function_id: RefCell::new(host_functions.len()), } } @@ -322,7 +321,7 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { if self.allow_missing_imports { trace!("Could not find function {}, a stub will be provided instead.", name); let id = self.missing_function_id.borrow().clone(); - self.missing_functions.borrow_mut().insert(id, name.to_string()); + self.missing_functions.borrow_mut().push(name.to_string()); *self.missing_function_id.borrow_mut() += 1; // NOTE: provide purposedly an invalid index of the function @@ -347,9 +346,12 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { .map_err(wasmi::Trap::from) .map(|v| v.map(Into::into)) } else if self.allow_missing_imports { - Err(Error::from( - format!("function {} does not exist", self.missing_functions[&index]) - ).into()) + Err(Error::from(format!( + "function {} does not exist", + self.missing_functions + .get(index - self.host_functions.len()) + .expect("invalid function index"), + )).into()) } else { Err(Error::from(format!("Could not find host function with index: {}", index)).into()) } @@ -389,7 +391,7 @@ fn call_in_wasm_module( data: &[u8], host_functions: &[&'static dyn Function], allow_missing_imports: bool, - missing_functions: &HashMap, + missing_functions: &Vec, ) -> Result, Error> { // extract a reference to a linear memory, optional reference to a table // and then initialize FunctionExecutor. @@ -438,7 +440,7 @@ fn instantiate_module( module: &Module, host_functions: &[&'static dyn Function], allow_missing_imports: bool, -) -> Result<(ModuleRef, HashMap), Error> { +) -> Result<(ModuleRef, Vec), Error> { let resolver = Resolver::new(host_functions, allow_missing_imports); // start module instantiation. Don't run 'start' function yet. let intermediate_instance = ModuleInstance::new( @@ -580,7 +582,7 @@ pub struct WasmiRuntime { /// Enable STUB for function called that are missing allow_missing_imports: bool, /// List of missing functions detected during function resolution - missing_functions: HashMap, + missing_functions: Vec, } impl WasmRuntime for WasmiRuntime { From cfd9b3bfab50b7456cece3f22437b27920dfa709 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 8 Jan 2020 12:48:47 +0100 Subject: [PATCH 20/41] WIP --- client/executor/wasmi/src/lib.rs | 2 +- primitives/runtime-interface/test/src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 1b9f06c59d0c0..54c06b433f6fd 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -324,7 +324,7 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { self.missing_functions.borrow_mut().push(name.to_string()); *self.missing_function_id.borrow_mut() += 1; - // NOTE: provide purposedly an invalid index of the function + // NOTE: provide purposely an invalid index of the function Ok(wasmi::FuncInstance::alloc_host(signature.into(), id)) } else { Err(wasmi::Error::Instantiation( diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index fb3d10b0234cf..d0b4f4371f769 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -41,6 +41,7 @@ fn call_wasm_method(method: &str) -> TestExternalities { &mut ext_ext, &WASM_BINARY[..], 8, + false, ).expect(&format!("Executes `{}`", method)); ext From b4b42d9b4a1f7bc8c1661a3ca4075b6d4b929cf8 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 8 Jan 2020 15:50:14 +0100 Subject: [PATCH 21/41] WIP --- client/executor/runtime-test/src/lib.rs | 5 -- client/executor/src/integration_tests/mod.rs | 63 +++++++++++++++++++- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/client/executor/runtime-test/src/lib.rs b/client/executor/runtime-test/src/lib.rs index 22694407b67ab..a8d329cdd9607 100644 --- a/client/executor/runtime-test/src/lib.rs +++ b/client/executor/runtime-test/src/lib.rs @@ -20,15 +20,12 @@ use sp_core::{ed25519, sr25519}; extern "C" { #[allow(dead_code)] - #[cfg(not(feature = "wasmtime"))] fn missing_external(); #[allow(dead_code)] - #[cfg(not(feature = "wasmtime"))] fn yet_another_missing_external(); } -#[cfg(not(feature = "wasmtime"))] sp_core::wasm_export_functions! { fn test_calling_missing_external() { unsafe { missing_external() } @@ -37,9 +34,7 @@ sp_core::wasm_export_functions! { fn test_calling_yet_another_missing_external() { unsafe { yet_another_missing_external() } } -} -sp_core::wasm_export_functions! { fn test_data_in(input: Vec) -> Vec { print("set_storage"); storage::set(b"input", &input); diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 3f685b93a528a..efeb0e7d6364c 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -32,6 +32,67 @@ use crate::WasmExecutionMethod; pub type TestExternalities = CoreTestExternalities; +#[cfg(feature = "wasmtime")] +mod wasmtime_missing_externals { + use sp_wasm_interface::{Function, FunctionContext, HostFunctions, Result, Signature, Value}; + + pub struct WasmtimeHostFunctions; + + impl HostFunctions for WasmtimeHostFunctions { + fn host_functions() -> Vec<&'static dyn Function> { + vec![MISSING_EXTERNAL_FUNCTION, YET_ANOTHER_MISSING_EXTERNAL_FUNCTION] + } + } + + struct MissingExternalFunction; + + impl Function for MissingExternalFunction { + fn name(&self) -> &str { "missing_external" } + + fn signature(&self) -> Signature { + Signature::new(vec![], None) + } + + fn execute( + &self, + _context: &mut dyn FunctionContext, + _args: &mut dyn Iterator, + ) -> Result> { + panic!("should not be called"); + } + } + + static MISSING_EXTERNAL_FUNCTION: &'static MissingExternalFunction = &MissingExternalFunction; + + struct YetAnotherMissingExternalFunction; + + impl Function for YetAnotherMissingExternalFunction { + fn name(&self) -> &str { "yet_another_missing_external" } + + fn signature(&self) -> Signature { + Signature::new(vec![], None) + } + + fn execute( + &self, + _context: &mut dyn FunctionContext, + _args: &mut dyn Iterator, + ) -> Result> { + panic!("should not be called"); + } + } + + static YET_ANOTHER_MISSING_EXTERNAL_FUNCTION: &'static YetAnotherMissingExternalFunction = + &YetAnotherMissingExternalFunction; +} + +#[cfg(feature = "wasmtime")] +type HostFunctions = + (wasmtime_missing_externals::WasmtimeHostFunctions, sp_io::SubstrateHostFunctions); + +#[cfg(not(feature = "wasmtime"))] +type HostFunctions = sp_io::SubstrateHostFunctions; + fn call_in_wasm( function: &str, call_data: &[u8], @@ -40,7 +101,7 @@ fn call_in_wasm( code: &[u8], heap_pages: u64, ) -> crate::error::Result> { - crate::call_in_wasm::( + crate::call_in_wasm::( function, call_data, execution_method, From 0e926a82f390fab622b107c2c9e860ee73f3ccc3 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 8 Jan 2020 17:34:28 +0100 Subject: [PATCH 22/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index d4fed137ac4f8..0ea6a0b9f7e1f 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -579,7 +579,8 @@ pub struct WasmiRuntime { state_snapshot: StateSnapshot, /// The host functions registered for this instance. host_functions: Vec<&'static dyn Function>, - /// Enable STUB for function called that are missing + /// Enable stub generation for functions that are not available in `host_functions`. + /// These stubs will error when the wasm blob tries to call them. allow_missing_imports: bool, /// List of missing functions detected during function resolution missing_functions: Vec, From 4c80f58258d633fb34f77430bc719e2f0c743875 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Wed, 8 Jan 2020 17:36:19 +0100 Subject: [PATCH 23/41] WIP --- client/executor/src/integration_tests/mod.rs | 30 ++++---------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index ad8eb7e66762b..dfc67c084878f 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -44,10 +44,10 @@ mod wasmtime_missing_externals { } } - struct MissingExternalFunction; + struct MissingExternalFunction(&'static str); impl Function for MissingExternalFunction { - fn name(&self) -> &str { "missing_external" } + fn name(&self) -> &str { self.0 } fn signature(&self) -> Signature { Signature::new(vec![], None) @@ -62,28 +62,10 @@ mod wasmtime_missing_externals { } } - static MISSING_EXTERNAL_FUNCTION: &'static MissingExternalFunction = &MissingExternalFunction; - - struct YetAnotherMissingExternalFunction; - - impl Function for YetAnotherMissingExternalFunction { - fn name(&self) -> &str { "yet_another_missing_external" } - - fn signature(&self) -> Signature { - Signature::new(vec![], None) - } - - fn execute( - &self, - _context: &mut dyn FunctionContext, - _args: &mut dyn Iterator, - ) -> Result> { - panic!("should not be called"); - } - } - - static YET_ANOTHER_MISSING_EXTERNAL_FUNCTION: &'static YetAnotherMissingExternalFunction = - &YetAnotherMissingExternalFunction; + static MISSING_EXTERNAL_FUNCTION: &'static MissingExternalFunction = + &MissingExternalFunction("missing_external"); + static YET_ANOTHER_MISSING_EXTERNAL_FUNCTION: &'static MissingExternalFunction = + &MissingExternalFunction("yet_another_missing_external"); } #[cfg(feature = "wasmtime")] From 36d8be2c8bc82eb434e08fd37a8982c6dcedb8d5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:52:47 +0100 Subject: [PATCH 24/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 0ea6a0b9f7e1f..0b57990ac4627 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -347,7 +347,7 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { .map(|v| v.map(Into::into)) } else if self.allow_missing_imports { Err(Error::from(format!( - "function {} does not exist", + "Function `{}` is only a stub. Calling a stub is not allowed.", self.missing_functions .get(index - self.host_functions.len()) .expect("invalid function index"), From 6786bf8213cbb64918df0c9a28e7e2dd59f0b1d6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:54:57 +0100 Subject: [PATCH 25/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 0b57990ac4627..b1d93c072029e 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -319,7 +319,7 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { } if self.allow_missing_imports { - trace!("Could not find function {}, a stub will be provided instead.", name); + trace!(target: "wasm-executor", "Could not find function `{}`, a stub will be provided instead.", name); let id = self.missing_function_id.borrow().clone(); self.missing_functions.borrow_mut().push(name.to_string()); *self.missing_function_id.borrow_mut() += 1; From 623787fe5cc9e1304ec40725a51b5018ea3733d3 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:55:15 +0100 Subject: [PATCH 26/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index b1d93c072029e..ab8270b47cf56 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -54,7 +54,7 @@ impl<'a> FunctionExecutor<'a> { t: Option, host_functions: &'a [&'static dyn Function], allow_missing_imports: bool, - missing_functions: &'a Vec, + missing_functions: &'a [String], ) -> Result { Ok(FunctionExecutor { sandbox_store: sandbox::Store::new(), From 000116e9cb53ba10194ca8d28931fd2a4656481c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:55:41 +0100 Subject: [PATCH 27/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index ab8270b47cf56..625bc7f11774a 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -21,7 +21,7 @@ use sc_executor_common::{ sandbox, allocator, }; -use std::{str, mem}; +use std::{str, mem, cell::RefCell}; use std::cell::RefCell; use wasmi::{ Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, From 131b7d43346c3c717e6ab66f18ca202cc3ee85b7 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:56:01 +0100 Subject: [PATCH 28/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 625bc7f11774a..e2b25804b6962 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -22,7 +22,6 @@ use sc_executor_common::{ allocator, }; use std::{str, mem, cell::RefCell}; -use std::cell::RefCell; use wasmi::{ Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, ModuleRef, memory_units::Pages, RuntimeValue::{I32, I64, self}, From 0b67996df36a06df46a267d307b328441ae9e148 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:56:17 +0100 Subject: [PATCH 29/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index e2b25804b6962..93ae792090a05 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -43,7 +43,7 @@ struct FunctionExecutor<'a> { table: Option, host_functions: &'a [&'static dyn Function], allow_missing_imports: bool, - missing_functions: &'a Vec, + missing_functions: &'a [String], } impl<'a> FunctionExecutor<'a> { From 2cb046981bc45d294e6ba3ae45b4c791d9f38c6a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:56:38 +0100 Subject: [PATCH 30/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 93ae792090a05..c8cefc3b15123 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -288,7 +288,6 @@ impl<'a> Resolver<'a> { host_functions, allow_missing_imports, missing_functions: RefCell::new(Vec::new()), - missing_function_id: RefCell::new(host_functions.len()), } } } From a5633f3bf65e049688bf6d5d8de6bb311275b9a5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:56:51 +0100 Subject: [PATCH 31/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index c8cefc3b15123..250e253c2ff27 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -279,7 +279,6 @@ struct Resolver<'a> { host_functions: &'a[&'static dyn Function], allow_missing_imports: bool, missing_functions: RefCell>, - missing_function_id: RefCell, } impl<'a> Resolver<'a> { From cd81107197e1a51810a148eee7379c70c3bbaa8d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:57:04 +0100 Subject: [PATCH 32/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 250e253c2ff27..45d03ba83846c 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -317,7 +317,7 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { if self.allow_missing_imports { trace!(target: "wasm-executor", "Could not find function `{}`, a stub will be provided instead.", name); - let id = self.missing_function_id.borrow().clone(); + let id = self.missing_functions.borrow().len() + self.host_functions.len(); self.missing_functions.borrow_mut().push(name.to_string()); *self.missing_function_id.borrow_mut() += 1; From cc1a4a87d213ff8e819e6e5b1370adf6ce46546e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:57:21 +0100 Subject: [PATCH 33/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 45d03ba83846c..9063e1cd879ed 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -319,7 +319,6 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { trace!(target: "wasm-executor", "Could not find function `{}`, a stub will be provided instead.", name); let id = self.missing_functions.borrow().len() + self.host_functions.len(); self.missing_functions.borrow_mut().push(name.to_string()); - *self.missing_function_id.borrow_mut() += 1; // NOTE: provide purposely an invalid index of the function Ok(wasmi::FuncInstance::alloc_host(signature.into(), id)) From 72898920a1614983f597ec5dc966add7cf615c90 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:57:40 +0100 Subject: [PATCH 34/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 9063e1cd879ed..30473c7acc287 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -320,7 +320,6 @@ impl<'a> wasmi::ModuleImportResolver for Resolver<'a> { let id = self.missing_functions.borrow().len() + self.host_functions.len(); self.missing_functions.borrow_mut().push(name.to_string()); - // NOTE: provide purposely an invalid index of the function Ok(wasmi::FuncInstance::alloc_host(signature.into(), id)) } else { Err(wasmi::Error::Instantiation( From 77fcaa5e0af4d4d635811cbd6011c3035b962a61 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:58:31 +0100 Subject: [PATCH 35/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 30473c7acc287..10a5b24466a7a 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -340,7 +340,7 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { .map_err(|msg| Error::FunctionExecution(function.name().to_string(), msg)) .map_err(wasmi::Trap::from) .map(|v| v.map(Into::into)) - } else if self.allow_missing_imports { + } else if self.allow_missing_imports && index >= self.host_functions.len() && index < self.host_functions.len() + self.missing_functions.len() { Err(Error::from(format!( "Function `{}` is only a stub. Calling a stub is not allowed.", self.missing_functions From 378502849c9e2ecc13b780dfcdaab228639ac609 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:58:52 +0100 Subject: [PATCH 36/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 10a5b24466a7a..0a80f2d69e5ad 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -343,7 +343,7 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { } else if self.allow_missing_imports && index >= self.host_functions.len() && index < self.host_functions.len() + self.missing_functions.len() { Err(Error::from(format!( "Function `{}` is only a stub. Calling a stub is not allowed.", - self.missing_functions + self.missing_functions[index - self.host_functions.len()] .get(index - self.host_functions.len()) .expect("invalid function index"), )).into()) From e78e4aa2de91827f767dac0cef0cfdec7e21a508 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:59:12 +0100 Subject: [PATCH 37/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 0a80f2d69e5ad..445475ef99e45 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -344,7 +344,6 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { Err(Error::from(format!( "Function `{}` is only a stub. Calling a stub is not allowed.", self.missing_functions[index - self.host_functions.len()] - .get(index - self.host_functions.len()) .expect("invalid function index"), )).into()) } else { From 63dc3ce733fda109104d8f2bb957ba5c858bdada Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 09:59:23 +0100 Subject: [PATCH 38/41] Update client/executor/wasmi/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- client/executor/wasmi/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 445475ef99e45..b00779b3a0295 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -344,7 +344,6 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { Err(Error::from(format!( "Function `{}` is only a stub. Calling a stub is not allowed.", self.missing_functions[index - self.host_functions.len()] - .expect("invalid function index"), )).into()) } else { Err(Error::from(format!("Could not find host function with index: {}", index)).into()) From 04a3db6dad283fc7806a9b695aa556fc2590859e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 10:01:35 +0100 Subject: [PATCH 39/41] WIP --- client/executor/wasmi/src/lib.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index b00779b3a0295..8bc1f8bbc4934 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -395,7 +395,13 @@ fn call_in_wasm_module( let heap_base = get_heap_base(module_instance)?; let mut fec = FunctionExecutor::new( - memory.clone(), heap_base, table, host_functions, allow_missing_imports, missing_functions)?; + memory.clone(), + heap_base, + table, + host_functions, + allow_missing_imports, + missing_functions, + )?; // Write the call data let offset = fec.allocate_memory(data.len() as u32)?; @@ -630,7 +636,11 @@ pub fn create_instance( // Instantiate this module. let (instance, missing_functions) = instantiate_module( - heap_pages as usize, &module, &host_functions, allow_missing_imports) + heap_pages as usize, + &module, + &host_functions, + allow_missing_imports, + ) .map_err(|e| WasmError::Instantiation(e.to_string()))?; // Take state snapshot before executing anything. From cc844f5604b6f2e11d6766ae50e470a8b9523525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Thu, 9 Jan 2020 10:08:06 +0100 Subject: [PATCH 40/41] Apply suggestions from code review --- client/executor/wasmi/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 8bc1f8bbc4934..1d01650b5b7c9 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -343,7 +343,7 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { } else if self.allow_missing_imports && index >= self.host_functions.len() && index < self.host_functions.len() + self.missing_functions.len() { Err(Error::from(format!( "Function `{}` is only a stub. Calling a stub is not allowed.", - self.missing_functions[index - self.host_functions.len()] + self.missing_functions[index - self.host_functions.len()], )).into()) } else { Err(Error::from(format!("Could not find host function with index: {}", index)).into()) @@ -640,8 +640,7 @@ pub fn create_instance( &module, &host_functions, allow_missing_imports, - ) - .map_err(|e| WasmError::Instantiation(e.to_string()))?; + ).map_err(|e| WasmError::Instantiation(e.to_string()))?; // Take state snapshot before executing anything. let state_snapshot = StateSnapshot::take(&instance, data_segments, heap_pages) From 199a60e5ff77b62fa23313b7ab24448eaff29bf5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Jan 2020 10:22:17 +0100 Subject: [PATCH 41/41] WIP --- client/executor/src/integration_tests/mod.rs | 4 ++-- client/executor/wasmi/src/lib.rs | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index dfc67c084878f..2d39cac414545 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -114,7 +114,7 @@ fn returning_should_work(wasm_method: WasmExecutionMethod) { #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "function missing_external does not exist")] +#[should_panic(expected = "Function `missing_external` is only a stub. Calling a stub is not allowed.")] #[cfg(not(feature = "wasmtime"))] fn call_not_existing_function(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); @@ -133,7 +133,7 @@ fn call_not_existing_function(wasm_method: WasmExecutionMethod) { #[test_case(WasmExecutionMethod::Interpreted)] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] -#[should_panic(expected = "function yet_another_missing_external does not exist")] +#[should_panic(expected = "Function `yet_another_missing_external` is only a stub. Calling a stub is not allowed.")] #[cfg(not(feature = "wasmtime"))] fn call_yet_another_not_existing_function(wasm_method: WasmExecutionMethod) { let mut ext = TestExternalities::default(); diff --git a/client/executor/wasmi/src/lib.rs b/client/executor/wasmi/src/lib.rs index 1d01650b5b7c9..7c6141d6c835f 100644 --- a/client/executor/wasmi/src/lib.rs +++ b/client/executor/wasmi/src/lib.rs @@ -340,7 +340,10 @@ impl<'a> wasmi::Externals for FunctionExecutor<'a> { .map_err(|msg| Error::FunctionExecution(function.name().to_string(), msg)) .map_err(wasmi::Trap::from) .map(|v| v.map(Into::into)) - } else if self.allow_missing_imports && index >= self.host_functions.len() && index < self.host_functions.len() + self.missing_functions.len() { + } else if self.allow_missing_imports + && index >= self.host_functions.len() + && index < self.host_functions.len() + self.missing_functions.len() + { Err(Error::from(format!( "Function `{}` is only a stub. Calling a stub is not allowed.", self.missing_functions[index - self.host_functions.len()],