diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 08ac226c0f88678d4b586640af789f507ec76107..ae875e940275e35e7ca17e98a4d2bc6531ba012d 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -2199,6 +2199,7 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-runtime-io 0.1.0", "substrate-runtime-std 0.1.0", + "wabt 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index e08fcfe565c51eb518db1befd05544fc6010c60f..ebbb66dec354eefb5549fd6e7b2fd6e36d8fbfee 100644 Binary files a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm and b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm differ diff --git a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm index 3d4eb2e456ee868b37c556c7ab39483ea18a90ef..3c9f7e9f7b0949126614cbf16b950e469bcc6a39 100755 Binary files a/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm and b/substrate/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.wasm differ diff --git a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm index 4e37cbbab1864b2a19bcb7a05309b97c385da44a..008e61b90b3c66ae29fd06590a93fea91d8e623f 100644 Binary files a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm and b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm differ diff --git a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm index 2d84f17d87db084e1a39f391940f7adb005125f1..e9d514e172316c11b859b18f54d8a3f76727a033 100755 Binary files a/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm and b/substrate/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm differ diff --git a/substrate/substrate/executor/src/sandbox.rs b/substrate/substrate/executor/src/sandbox.rs index 682014d235ed0bdd5832c60303fb5ae32db4f8da..51cbb85fb5a0325eb79cd19131b1c9cd081cb037 100644 --- a/substrate/substrate/executor/src/sandbox.rs +++ b/substrate/substrate/executor/src/sandbox.rs @@ -25,8 +25,10 @@ use primitives::sandbox as sandbox_primitives; use wasm_utils::DummyUserError; use wasmi; use wasmi::memory_units::Pages; -use wasmi::{Externals, FuncRef, ImportResolver, MemoryInstance, MemoryRef, Module, ModuleInstance, - ModuleRef, RuntimeArgs, RuntimeValue, Trap, TrapKind}; +use wasmi::{ + Externals, FuncRef, ImportResolver, MemoryInstance, MemoryRef, Module, ModuleInstance, + ModuleRef, RuntimeArgs, RuntimeValue, Trap, TrapKind +}; /// Index of a function inside the supervisor. /// @@ -111,22 +113,26 @@ impl ImportResolver for Imports { fn resolve_global( &self, - _module_name: &str, - _field_name: &str, + module_name: &str, + field_name: &str, _global_type: &::wasmi::GlobalDescriptor, ) -> Result<::wasmi::GlobalRef, ::wasmi::Error> { - // TODO: - unimplemented!() + Err(::wasmi::Error::Instantiation(format!( + "Export {}:{} not found", + module_name, field_name + ))) } fn resolve_table( &self, - _module_name: &str, - _field_name: &str, + module_name: &str, + field_name: &str, _table_type: &::wasmi::TableDescriptor, ) -> Result<::wasmi::TableRef, ::wasmi::Error> { - // TODO: - unimplemented!() + Err(::wasmi::Error::Instantiation(format!( + "Export {}:{} not found", + module_name, field_name + ))) } } @@ -259,7 +265,8 @@ impl<'a, FE: SandboxCapabilities + Externals + 'a> Externals for GuestExternals< self.supervisor_externals .deallocate(serialized_result_val_ptr); - // TODO: check the signature? + // We do not have to check the signature here, because it's automatically + // checked by wasmi. deserialize_result(&serialized_result_val) } @@ -610,4 +617,60 @@ mod tests { vec![1], ); } + + #[test] + fn invoke_args() { + let mut ext = TestExternalities::default(); + let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + + (func (export "call") (param $x i32) (param $y i64) + ;; assert that $x = 0x12345678 + (call $assert + (i32.eq + (get_local $x) + (i32.const 0x12345678) + ) + ) + + (call $assert + (i64.eq + (get_local $y) + (i64.const 0x1234567887654321) + ) + ) + ) + ) + "#).unwrap(); + + assert_eq!( + WasmExecutor.call(&mut ext, &test_code[..], "test_sandbox_args", &code).unwrap(), + vec![1], + ); + } + + #[test] + fn return_val() { + let mut ext = TestExternalities::default(); + let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); + + let code = wabt::wat2wasm(r#" + (module + (func (export "call") (param $x i32) (result i32) + (i32.add + (get_local $x) + (i32.const 1) + ) + ) + ) + "#).unwrap(); + + assert_eq!( + WasmExecutor.call(&mut ext, &test_code[..], "test_sandbox_return_val", &code).unwrap(), + vec![1], + ); + } } diff --git a/substrate/substrate/executor/src/wasm_executor.rs b/substrate/substrate/executor/src/wasm_executor.rs index 20633449b5c7d34fc520ca984800ca358b028948..1f71a807b4f50aa15acb4c935f7df8fd1e01cc5b 100644 --- a/substrate/substrate/executor/src/wasm_executor.rs +++ b/substrate/substrate/executor/src/wasm_executor.rs @@ -360,7 +360,9 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.sandbox_store.instance_teardown(instance_idx)?; Ok(()) }, - ext_sandbox_invoke(instance_idx: u32, export_ptr: *const u8, export_len: usize, state: usize) -> u32 => { + ext_sandbox_invoke(instance_idx: u32, export_ptr: *const u8, export_len: usize, args_ptr: *const u8, args_len: usize, return_val_ptr: *const u8, return_val_len: usize, state: usize) -> u32 => { + use codec::Slicable; + trace!(target: "runtime-sandbox", "invoke, instance_idx={}", instance_idx); let export = this.memory.get(export_ptr, export_len as usize) .map_err(|_| DummyUserError) @@ -369,12 +371,32 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, .map_err(|_| DummyUserError) )?; + // Deserialize arguments and convert them into wasmi types. + let serialized_args = this.memory.get(args_ptr, args_len as usize) + .map_err(|_| DummyUserError)?; + let args = Vec::<sandbox_primitives::TypedValue>::decode(&mut &serialized_args[..]) + .ok_or_else(|| DummyUserError)? + .into_iter() + .map(Into::into) + .collect::<Vec<_>>(); + let instance = this.sandbox_store.instance(instance_idx)?; - let result = instance.invoke(&export, &[], this, state); + let result = instance.invoke(&export, &args, this, state); + match result { Ok(None) => Ok(sandbox_primitives::ERR_OK), - // TODO: Return value - Ok(_) => unimplemented!(), + Ok(Some(val)) => { + // Serialize return value and write it back into the memory. + sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| { + if val.len() > return_val_len as usize { + Err(DummyUserError)?; + } + this.memory + .set(return_val_ptr, val) + .map_err(|_| DummyUserError)?; + Ok(sandbox_primitives::ERR_OK) + }) + } Err(_) => Ok(sandbox_primitives::ERR_EXECUTION), } }, diff --git a/substrate/substrate/executor/wasm/src/lib.rs b/substrate/substrate/executor/wasm/src/lib.rs index 8d993292396933284713e4a68628d47a335d7011..804dd3b89cb77a64578b7db6cd754475c61140a2 100644 --- a/substrate/substrate/executor/wasm/src/lib.rs +++ b/substrate/substrate/executor/wasm/src/lib.rs @@ -54,12 +54,32 @@ impl_stubs!( enumerated_trie_root(&[&b"zero"[..], &b"one"[..], &b"two"[..]]).to_vec() }, test_sandbox NO_DECODE => |code: &[u8]| { - let result = execute_sandboxed(code).is_ok(); - [result as u8].to_vec() + let ok = execute_sandboxed(code, &[]).is_ok(); + [ok as u8].to_vec() + }, + test_sandbox_args NO_DECODE => |code: &[u8]| { + let ok = execute_sandboxed( + code, + &[ + sandbox::TypedValue::I32(0x12345678), + sandbox::TypedValue::I64(0x1234567887654321), + ] + ).is_ok(); + [ok as u8].to_vec() + }, + test_sandbox_return_val NO_DECODE => |code: &[u8]| { + let result = execute_sandboxed( + code, + &[ + sandbox::TypedValue::I32(0x1336), + ] + ); + let ok = if let Ok(sandbox::ReturnValue::Value(sandbox::TypedValue::I32(0x1337))) = result { true } else { false }; + [ok as u8].to_vec() } ); -fn execute_sandboxed(code: &[u8]) -> Result<sandbox::ReturnValue, sandbox::HostError> { +fn execute_sandboxed(code: &[u8], args: &[sandbox::TypedValue]) -> Result<sandbox::ReturnValue, sandbox::HostError> { struct State { counter: u32, } @@ -91,7 +111,7 @@ fn execute_sandboxed(code: &[u8]) -> Result<sandbox::ReturnValue, sandbox::HostE env_builder.add_host_func("env", "inc_counter", env_inc_counter); let mut instance = sandbox::Instance::new(code, &env_builder, &mut state)?; - let result = instance.invoke(b"call", &[], &mut state); + let result = instance.invoke(b"call", args, &mut state); result.map_err(|_| sandbox::HostError) } diff --git a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm index d62a456ea44ea8733a1198052834b533b8e08044..d77bb7c40240487670ba4a94b4903ad48032f2b2 100644 Binary files a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm and b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm differ diff --git a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm index b470be1870577bb4e357acdbed801be9c6e811c3..303b99226d04ffb79ee105f8234b02f7e12aadca 100755 Binary files a/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm and b/substrate/substrate/executor/wasm/target/wasm32-unknown-unknown/release/runtime_test.wasm differ diff --git a/substrate/substrate/primitives/src/sandbox.rs b/substrate/substrate/primitives/src/sandbox.rs index 71d22afa9f4d13616eacea206e44ff4f30ef58bb..3fc8abc302c4c7e53c821ac3dae4adc1eb8dfecc 100644 --- a/substrate/substrate/primitives/src/sandbox.rs +++ b/substrate/substrate/primitives/src/sandbox.rs @@ -180,6 +180,23 @@ impl Slicable for ReturnValue { } } +impl ReturnValue { + /// Maximum number of bytes `ReturnValue` might occupy when serialized with + /// `Slicable`. + /// + /// Breakdown: + /// 1 byte for encoding unit/value variant + /// 1 byte for encoding value type + /// 8 bytes for encoding the biggest value types available in wasm: f64, i64. + pub const ENCODED_MAX_SIZE: usize = 10; +} + +#[test] +fn return_value_encoded_max_size() { + let encoded = ReturnValue::Value(TypedValue::I64(-1)).encode(); + assert_eq!(encoded.len(), ReturnValue::ENCODED_MAX_SIZE); +} + #[derive(Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Debug))] #[repr(i8)] diff --git a/substrate/substrate/runtime-io/without_std.rs b/substrate/substrate/runtime-io/without_std.rs index 9e145aa853a1ab69ac63568ad53c01ac5718d992..3f8e1f31072a293225f1010e0b80c93c0fbdaa4b 100644 --- a/substrate/substrate/runtime-io/without_std.rs +++ b/substrate/substrate/runtime-io/without_std.rs @@ -29,12 +29,12 @@ pub use rstd::{mem, slice}; #[panic_implementation] #[no_mangle] -pub fn panic(_info: &core::panic::PanicInfo) -> ! { +pub fn panic(info: &::core::panic::PanicInfo) -> ! { unsafe { - if let Some(location) = _info.location() { - ext_print_utf8(location.file().as_ptr() as *const u8, location.file().len() as u32); - ext_print_num(location.line() as u64); - ext_print_num(location.column() as u64); + if let Some(loc) = info.location() { + ext_print_utf8(loc.file().as_ptr() as *const u8, loc.file().len() as u32); + ext_print_num(loc.line() as u64); + ext_print_num(loc.column() as u64); } intrinsics::abort() } diff --git a/substrate/substrate/runtime-sandbox/Cargo.toml b/substrate/substrate/runtime-sandbox/Cargo.toml index c47ef3ecbc846afcae2840a69f7bea30e24225ea..c6d4a930907b7464d9804a27e819991a9ff95fb3 100755 --- a/substrate/substrate/runtime-sandbox/Cargo.toml +++ b/substrate/substrate/runtime-sandbox/Cargo.toml @@ -14,6 +14,9 @@ substrate-runtime-std = { path = "../runtime-std", default_features = false } substrate-runtime-io = { path = "../runtime-io", default_features = false } substrate-codec = { path = "../codec", default_features = false } +[dev-dependencies] +wabt = "0.1.7" + [features] default = ["std"] std = [ diff --git a/substrate/substrate/runtime-sandbox/src/lib.rs b/substrate/substrate/runtime-sandbox/src/lib.rs index 6c71c085bc3f5591fbaef456da1a4950a5668420..f9195c10efe46814089399560f94215ba660c917 100755 --- a/substrate/substrate/runtime-sandbox/src/lib.rs +++ b/substrate/substrate/runtime-sandbox/src/lib.rs @@ -40,9 +40,13 @@ extern crate substrate_codec as codec; extern crate substrate_runtime_io as runtime_io; +#[cfg_attr(not(feature = "std"), macro_use)] extern crate substrate_runtime_std as rstd; extern crate substrate_primitives as primitives; +#[cfg(test)] +extern crate wabt; + use rstd::prelude::*; pub use primitives::sandbox::{TypedValue, ReturnValue, HostError}; diff --git a/substrate/substrate/runtime-sandbox/with_std.rs b/substrate/substrate/runtime-sandbox/with_std.rs index 5be7b494a779103dedf16d83ff1241a2a1cc6af9..aee9fda81306022e1ee809f4474361c93633dc13 100755 --- a/substrate/substrate/runtime-sandbox/with_std.rs +++ b/substrate/substrate/runtime-sandbox/with_std.rs @@ -20,9 +20,11 @@ use rstd::collections::btree_map::BTreeMap; use rstd::fmt; -use self::wasmi::{Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalRef, ImportResolver, - MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleInstance, ModuleRef, - RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableRef, Trap, TrapKind}; +use self::wasmi::{ + Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalRef, ImportResolver, + MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleInstance, ModuleRef, + RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableRef, Trap, TrapKind +}; use self::wasmi::memory_units::Pages; use super::{Error, TypedValue, ReturnValue, HostFuncType, HostError}; @@ -208,8 +210,9 @@ impl<T> ImportResolver for EnvironmentDefinitionBuilder<T> { _field_name: &str, _global_type: &GlobalDescriptor, ) -> Result<GlobalRef, wasmi::Error> { - // TODO: Implement sandboxed globals. - unimplemented!() + Err(wasmi::Error::Instantiation(format!( + "Importing globals is not supported yet" + ))) } fn resolve_memory( @@ -243,8 +246,9 @@ impl<T> ImportResolver for EnvironmentDefinitionBuilder<T> { _field_name: &str, _table_type: &TableDescriptor, ) -> Result<TableRef, wasmi::Error> { - // TODO: Implement sandboxed tables. - unimplemented!() + Err(wasmi::Error::Instantiation(format!( + "Importing tables is not supported yet" + ))) } } @@ -284,10 +288,7 @@ impl<T> Instance<T> { args: &[TypedValue], state: &mut T, ) -> Result<ReturnValue, Error> { - if args.len() > 0 { - // TODO: Convert args into `RuntimeValue` and use it. - unimplemented!(); - } + let args = args.iter().cloned().map(Into::into).collect::<Vec<_>>(); let name = ::std::str::from_utf8(name).map_err(|_| Error::Execution)?; let mut externals = GuestExternals { @@ -295,15 +296,112 @@ impl<T> Instance<T> { defined_host_functions: &self.defined_host_functions, }; let result = self.instance - .invoke_export(&name, &[], &mut externals); + .invoke_export(&name, &args, &mut externals); match result { Ok(None) => Ok(ReturnValue::Unit), - Ok(_val) => { - // TODO: Convert result value into `TypedValue` and return it. - unimplemented!(); - } + Ok(Some(val)) => Ok(ReturnValue::Value(val.into())), Err(_err) => Err(Error::Execution), } } } + +#[cfg(test)] +mod tests { + use wabt; + use ::{TypedValue, ReturnValue, HostError, EnvironmentDefinitionBuilder, Instance}; + + fn execute_sandboxed(code: &[u8], args: &[TypedValue]) -> Result<ReturnValue, HostError> { + struct State { + counter: u32, + } + + fn env_assert(_e: &mut State, args: &[TypedValue]) -> Result<ReturnValue, HostError> { + if args.len() != 1 { + return Err(HostError); + } + let condition = args[0].as_i32().ok_or_else(|| HostError)?; + if condition != 0 { + Ok(ReturnValue::Unit) + } else { + Err(HostError) + } + } + fn env_inc_counter(e: &mut State, args: &[TypedValue]) -> Result<ReturnValue, HostError> { + if args.len() != 1 { + return Err(HostError); + } + let inc_by = args[0].as_i32().ok_or_else(|| HostError)?; + e.counter += inc_by as u32; + Ok(ReturnValue::Value(TypedValue::I32(e.counter as i32))) + } + + let mut state = State { counter: 0 }; + + let mut env_builder = EnvironmentDefinitionBuilder::new(); + env_builder.add_host_func("env", "assert", env_assert); + env_builder.add_host_func("env", "inc_counter", env_inc_counter); + + let mut instance = Instance::new(code, &env_builder, &mut state)?; + let result = instance.invoke(b"call", args, &mut state); + + result.map_err(|_| HostError) + } + + #[test] + fn invoke_args() { + let code = wabt::wat2wasm(r#" + (module + (import "env" "assert" (func $assert (param i32))) + + (func (export "call") (param $x i32) (param $y i64) + ;; assert that $x = 0x12345678 + (call $assert + (i32.eq + (get_local $x) + (i32.const 0x12345678) + ) + ) + + (call $assert + (i64.eq + (get_local $y) + (i64.const 0x1234567887654321) + ) + ) + ) + ) + "#).unwrap(); + + let result = execute_sandboxed( + &code, + &[ + TypedValue::I32(0x12345678), + TypedValue::I64(0x1234567887654321), + ] + ); + assert!(result.is_ok()); + } + + #[test] + fn return_value() { + let code = wabt::wat2wasm(r#" + (module + (func (export "call") (param $x i32) (result i32) + (i32.add + (get_local $x) + (i32.const 1) + ) + ) + ) + "#).unwrap(); + + let return_val = execute_sandboxed( + &code, + &[ + TypedValue::I32(0x1336), + ] + ).unwrap(); + assert_eq!(return_val, ReturnValue::Value(TypedValue::I32(0x1337))); + } +} diff --git a/substrate/substrate/runtime-sandbox/without_std.rs b/substrate/substrate/runtime-sandbox/without_std.rs index edcbeb2d1f9362ad88aad08da59c069d992e82bf..1d205bd7a6978378d69354d14f8da830ce7e7275 100755 --- a/substrate/substrate/runtime-sandbox/without_std.rs +++ b/substrate/substrate/runtime-sandbox/without_std.rs @@ -61,6 +61,10 @@ mod ffi { instance_idx: u32, export_ptr: *const u8, export_len: usize, + args_ptr: *const u8, + args_len: usize, + return_val_ptr: *mut u8, + return_val_len: usize, state: usize, ) -> u32; pub fn ext_sandbox_memory_new(initial: u32, maximum: u32) -> u32; @@ -260,16 +264,29 @@ impl<T> Instance<T> { pub fn invoke( &mut self, name: &[u8], - _args: &[TypedValue], + args: &[TypedValue], state: &mut T, ) -> Result<ReturnValue, Error> { - // TODO: Serialize arguments and pass them thru. - let result = - unsafe { ffi::ext_sandbox_invoke(self.instance_idx, name.as_ptr(), name.len(), state as *const T as usize) }; + let serialized_args = args.to_vec().encode(); + let mut return_val = vec![0u8; sandbox_primitives::ReturnValue::ENCODED_MAX_SIZE]; + + let result = unsafe { + ffi::ext_sandbox_invoke( + self.instance_idx, + name.as_ptr(), + name.len(), + serialized_args.as_ptr(), + serialized_args.len(), + return_val.as_mut_ptr(), + return_val.len(), + state as *const T as usize, + ) + }; match result { sandbox_primitives::ERR_OK => { - // TODO: Fetch the result of the execution. - Ok(ReturnValue::Unit) + let return_val = sandbox_primitives::ReturnValue::decode(&mut &return_val[..]) + .ok_or(Error::Execution)?; + Ok(return_val) } sandbox_primitives::ERR_EXECUTION => Err(Error::Execution), _ => unreachable!(), diff --git a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index a16b0b0db6cc9b87984dd39a38f4e264310cf236..b25935b6ab4c938674c1d9028ce81a20edb3d24d 100644 Binary files a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm index 5cdc00652a1fa6f4dd76051e83541d6f02c7bf6d..eeb6c52d370ae91119a2a3e40c72b36faedfa743 100755 Binary files a/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm and b/substrate/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm differ