From 8ad113924e8471514908783beb68edf4ed3a50aa Mon Sep 17 00:00:00 2001 From: Arsenii Lyashenko Date: Sun, 29 Sep 2024 23:46:02 +0300 Subject: [PATCH] chore(tooling): Use wasmer instead of wasmi (#4261) --- Cargo.lock | 90 ++------- Cargo.toml | 12 +- gcli/Cargo.toml | 4 +- gcli/src/meta/executor.rs | 180 +++++++++--------- gcli/src/result.rs | 4 +- sandbox/host/Cargo.toml | 6 +- sandbox/host/src/sandbox.rs | 2 +- sandbox/host/src/sandbox/wasmer_backend.rs | 131 ++++++------- .../host/src/sandbox/wasmer_backend/cache.rs | 7 +- .../sandbox/wasmer_backend/store_refcell.rs | 6 +- utils/calc-stack-height/Cargo.toml | 4 +- utils/calc-stack-height/src/main.rs | 6 +- utils/crates-io/src/handler.rs | 19 +- utils/crates-io/src/manifest.rs | 3 +- utils/lazy-pages-fuzzer/Cargo.toml | 2 +- utils/lazy-pages-fuzzer/src/wasmer_backend.rs | 2 +- utils/wasm-builder/Cargo.toml | 1 - utils/wasm-optimizer/Cargo.toml | 2 +- utils/wasm-optimizer/src/stack_end.rs | 73 +++---- 19 files changed, 224 insertions(+), 330 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2860da7a742..edcefd2611e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1792,8 +1792,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ "bitcoin_hashes 0.11.0", - "rand 0.7.3", - "rand_core 0.5.1", + "rand 0.8.5", + "rand_core 0.6.4", "serde", "unicode-normalization", ] @@ -6319,7 +6319,8 @@ dependencies = [ "tokio", "toml 0.8.14", "url", - "wasmi 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer", + "wasmer-types", "which", "whoami", ] @@ -6550,7 +6551,7 @@ dependencies = [ "scale-info", "serde", "wabt", - "wasmparser-nostd 0.100.1", + "wasmparser-nostd", ] [[package]] @@ -6861,7 +6862,7 @@ dependencies = [ "sp-core", "sp-std 8.0.0", "sp-wasm-interface-common", - "wasmi 0.30.0 (git+https://github.com/gear-tech/wasmi?branch=gear-v0.30.0)", + "wasmi 0.30.0", "wat", ] @@ -7061,7 +7062,6 @@ dependencies = [ "thiserror", "toml 0.8.14", "wabt", - "wasmi 0.14.0", ] [[package]] @@ -7086,7 +7086,7 @@ dependencies = [ "rand 0.8.5", "thiserror", "wasm-smith", - "wasmparser-nostd 0.100.1", + "wasmparser-nostd", "wasmprinter", "wat", ] @@ -7098,7 +7098,7 @@ dependencies = [ "derive_more 0.99.18", "enum-iterator 1.5.0", "gwasm-instrument", - "wasmparser-nostd 0.100.1", + "wasmparser-nostd", "wat", ] @@ -7115,8 +7115,8 @@ dependencies = [ "rustc_version 0.4.0", "wabt", "wasm-opt", - "wasmi 0.14.0", - "wasmparser-nostd 0.100.1", + "wasmer", + "wasmparser-nostd", "which", ] @@ -18655,7 +18655,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand 0.7.3", + "rand 0.8.5", "static_assertions", ] @@ -19472,32 +19472,7 @@ source = "git+https://github.com/gear-tech/wasmi?branch=v0.13.2-sign-ext#3a0b102 dependencies = [ "parity-wasm", "wasmi-validation", - "wasmi_core 0.2.1 (git+https://github.com/gear-tech/wasmi?branch=v0.13.2-sign-ext)", -] - -[[package]] -name = "wasmi" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae73f0dc2c05c94f30cb04498c67574b7588d0e674cc9255b96a05d21345528c" -dependencies = [ - "spin 0.9.8", - "wasmi_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmparser-nostd 0.83.0", -] - -[[package]] -name = "wasmi" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51fb5c61993e71158abf5bb863df2674ca3ec39ed6471c64f07aeaf751d67b4" -dependencies = [ - "intx", - "smallvec", - "spin 0.9.8", - "wasmi_arena 0.4.1", - "wasmi_core 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmparser-nostd 0.100.1", + "wasmi_core 0.2.1", ] [[package]] @@ -19509,8 +19484,8 @@ dependencies = [ "smallvec", "spin 0.9.8", "wasmi_arena 0.4.0", - "wasmi_core 0.12.0 (git+https://github.com/gear-tech/wasmi?branch=gear-v0.30.0)", - "wasmparser-nostd 0.100.1", + "wasmi_core 0.12.0", + "wasmparser-nostd", ] [[package]] @@ -19523,7 +19498,7 @@ dependencies = [ "spin 0.9.8", "wasmi_arena 0.4.1", "wasmi_core 0.13.0", - "wasmparser-nostd 0.100.1", + "wasmparser-nostd", ] [[package]] @@ -19545,19 +19520,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" -[[package]] -name = "wasmi_core" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d20cb3c59b788653d99541c646c561c9dd26506f25c0cebfe810659c54c6d7" -dependencies = [ - "downcast-rs", - "libm", - "memory_units", - "num-rational", - "num-traits", -] - [[package]] name = "wasmi_core" version = "0.2.1" @@ -19571,18 +19533,6 @@ dependencies = [ "region", ] -[[package]] -name = "wasmi_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624e6333e861ef49095d2d678b76ebf30b06bf37effca845be7e5b87c90071b7" -dependencies = [ - "downcast-rs", - "libm", - "num-traits", - "paste", -] - [[package]] name = "wasmi_core" version = "0.12.0" @@ -19649,15 +19599,9 @@ dependencies = [ [[package]] name = "wasmparser-nostd" -version = "0.83.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58a45f1058fed5ce7ff3da64153d0537a1ae664d09855fbb1402c6472f09571b" - -[[package]] -name = "wasmparser-nostd" -version = "0.100.1" +version = "0.100.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" dependencies = [ "indexmap-nostd", ] diff --git a/Cargo.toml b/Cargo.toml index 81a1803ca58..2635f1a4b02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,7 +181,6 @@ wabt = "0.10.0" wasmer = "4.3.4" wasmer-cache = "4.3.4" wasmer-types = "4.3.4" -wasmi = { version = "0.14.0", default-features = false } wasmtime = "8.0.1" wasmparser = { package = "wasmparser-nostd", version = "0.100.1", default-features = false } which = "4.4.2" @@ -303,11 +302,7 @@ ethexe-validator = { path = "ethexe/validator", default-features = false } ethexe-rpc = { path = "ethexe/rpc", default-features = false } ethexe-common = { path = "ethexe/common" } -# Common executors between `sandbox-host` and `calc-stack-height` -sandbox-wasmer = { package = "wasmer", version = "4.3.4", features = [ - "singlepass", -] } -sandbox-wasmer-types = { package = "wasmer-types", version = "4.3.4" } +# Common executor between `sandbox-host` and `lazy-pages-fuzzer` sandbox-wasmi = { package = "wasmi", git = "https://github.com/gear-tech/wasmi", branch = "v0.13.2-sign-ext", features = [ "virtual_memory", ] } @@ -542,11 +537,6 @@ num-traits = { version = "0.2", default-features = false } # gear-core glob = "0.3.1" # cargo-gbuild smallvec = "1.13.2" # utils/node-wrapper -# TODO: remove after wasmer bug is fixed: -# `misaligned pointer dereference: address must be a multiple of 0x8 but is...` -[profile.dev.package."wasmer-vm"] -debug-assertions = false - [profile.release] panic = "unwind" diff --git a/gcli/Cargo.toml b/gcli/Cargo.toml index d399ecd8d9a..5c37586644f 100644 --- a/gcli/Cargo.toml +++ b/gcli/Cargo.toml @@ -40,8 +40,8 @@ etc.workspace = true runtime-primitives.workspace = true url = { workspace = true, features = ["serde"] } toml.workspace = true -# TODO: use wasmi from workspace (#3214) -wasmi = { version = "0.30.0", features = ["std"] } +wasmer = { workspace = true, features = ["std"] } +wasmer-types.workspace = true [dev-dependencies] rand.workspace = true diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 60394cf559b..30151506c11 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -20,8 +20,8 @@ //! of gear programs, some of the host functions are missing logics that //! is because they are for the on-chain environment data. -use anyhow::{anyhow, Result}; -use wasmi::{AsContextMut, Engine, Extern, Linker, Memory, MemoryType, Module, Store}; +use anyhow::{anyhow, Context, Result}; +use wasmer::{Engine, FunctionEnv, Imports, Instance, Memory, MemoryType, Module, Store}; /// HostState for the WASM executor #[derive(Default)] @@ -40,20 +40,20 @@ fn execute(wasm: &[u8], method: &str) -> Result> { let engine = Engine::default(); let module = Module::new(&engine, wasm).unwrap(); - let mut store = Store::new(&engine, HostState::default()); - let mut linker = >::new(&engine); - let memory = Memory::new( - store.as_context_mut(), - MemoryType::new(256, None).map_err(|_| anyhow!("failed to create memory type"))?, - ) - .map_err(|_| anyhow!("failed to create memory"))?; + let mut store = Store::new(engine); + let memory_type = MemoryType::new(256, None, false); + let memory = + Memory::new(&mut store, memory_type).map_err(|_| anyhow!("failed to create memory"))?; + let mut imports = Imports::new(); + let state = FunctionEnv::new(&mut store, HostState::default()); // Execution environment // // TODO: refactor this after #3416. { let mut env = env::Env { - linker: &mut linker, + imports: &mut imports, + function_env: &state, store: &mut store, memory, }; @@ -63,33 +63,27 @@ fn execute(wasm: &[u8], method: &str) -> Result> { } } - let instance = linker - .instantiate(&mut store, &module) - .unwrap() - .start(&mut store)?; - + let instance = Instance::new(&mut store, &module, &imports)?; let metadata = instance - .get_export(&store, method) - .and_then(Extern::into_func) - .ok_or_else(|| anyhow!("could not find function \"{}\"", method))? - .typed::<(), ()>(&mut store)?; - - metadata.call(&mut store, ())?; - Ok(store.data().msg.clone()) + .exports + .get_function(method) + .with_context(|| format!(r#"could not find function "{method}""#))? + .typed::<(), ()>(&store)?; + metadata.call(&mut store)?; + Ok(state.as_ref(&store).msg.clone()) } mod env { use super::HostState; use anyhow::{anyhow, Result}; - use wasmi::{ - core::{Pages, Trap, TrapCode}, - AsContext, AsContextMut, Caller, Extern, Func, Linker, Memory, Store, - }; + use wasmer::{Extern, Function, FunctionEnv, FunctionEnvMut, Imports, Memory, Pages, Store}; + use wasmer_types::TrapCode; /// Environment for the wasm execution. pub struct Env<'e> { - pub linker: &'e mut Linker, - pub store: &'e mut Store, + pub imports: &'e mut Imports, + pub function_env: &'e FunctionEnv, + pub store: &'e mut Store, pub memory: Memory, } @@ -98,15 +92,15 @@ mod env { func!($store,) }; ($store:tt, $($ty:tt),* ) => { - Extern::Func(Func::wrap( + Extern::Function(Function::new_typed( $store, - move |_caller: Caller<'_, HostState>, $(_: $ty),*| { Ok(()) }, + move |$(_: $ty),*| { }, )) }; (@result $store:tt, $($ty:tt),* ) => { - Extern::Func(Func::wrap( + Extern::Function(Function::new_typed( $store, - move |_caller: Caller<'_, HostState>, $(_: $ty),*| { 0 }, + move |$(_: $ty),*| { 0 }, )) }; } @@ -118,17 +112,17 @@ mod env { return Err(anyhow!("module \"{}\" not found", module)); } - let memory = self.memory; + let memory = self.memory.clone(); let store = &mut self.store; let external = match name { "memory" => Extern::Memory(memory), - "alloc" => alloc(self.store, memory), + "alloc" => alloc(self.store, self.function_env, memory), "gr_oom_panic" => gr_oom_panic(store), - "gr_read" => gr_read(store, memory), - "gr_reply" => gr_reply(store, memory), - "gr_panic" => gr_panic(store, memory), - "gr_size" => gr_size(store, memory), + "gr_read" => gr_read(store, self.function_env, memory), + "gr_reply" => gr_reply(store, self.function_env, memory), + "gr_panic" => gr_panic(store, self.function_env, memory), + "gr_size" => gr_size(store, self.function_env, memory), // methods may be used by programs but not required by metadata. "free" => func!(@result store, i32), "free_range" => func!(@result store, i32, i32), @@ -179,101 +173,100 @@ mod env { _ => return Err(anyhow!("export \"{}\" not found in env", name,)), }; - self.linker.define(module, name, external)?; + self.imports.define(module, name, external); Ok(()) } } - fn alloc(store: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( + fn alloc(store: &mut Store, env: &FunctionEnv, memory: Memory) -> Extern { + Extern::Function(Function::new_typed_with_env( store, - move |mut caller: Caller<'_, HostState>, pages: u32| { - memory - .clone() - .grow( - caller.as_context_mut(), - Pages::new(pages).unwrap_or_default(), - ) - .map_or_else( - |err| { - log::error!("{err:?}"); - u32::MAX as i32 - }, - |pages| pages.to_bytes().unwrap_or_default() as i32, - ) + env, + move |mut env: FunctionEnvMut, pages: u32| { + memory.grow(&mut env, Pages::from(pages)).map_or_else( + |err| { + log::error!("{err:?}"); + u32::MAX as i32 + }, + |pages| pages.bytes().0 as u32 as i32, + ) }, )) } - fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( + fn gr_read(ctx: &mut Store, env: &FunctionEnv, memory: Memory) -> Extern { + Extern::Function(Function::new_typed_with_env( ctx, - move |mut caller: Caller<'_, HostState>, at: u32, len: i32, buff: i32, err: i32| { + env, + move |mut env: FunctionEnvMut, at: u32, len: i32, buff: i32, err: i32| { + let (data, store) = env.data_and_store_mut(); let (at, len, buff, err) = (at as _, len as usize, buff as _, err as _); - let msg = &caller.data().msg; + let msg = &data.msg; let payload = if at + len <= msg.len() { msg[at..(at + len)].to_vec() } else { - return Err(Trap::new(TrapCode::MemoryOutOfBounds.trap_message())); + return Err(TrapCode::HeapAccessOutOfBounds); }; + let memory = memory.view(&store); + let len: u32 = memory - .clone() - .write(caller.as_context_mut(), buff, &payload) + .write(buff, &payload) .map_err(|e| log::error!("{:?}", e)) .is_err() .into(); - memory - .clone() - .write(caller.as_context_mut(), err, &len.to_le_bytes()) - .map_err(|e| { - log::error!("{:?}", e); - Trap::new(TrapCode::MemoryOutOfBounds.trap_message()) - })?; + memory.write(err, &len.to_le_bytes()).map_err(|e| { + log::error!("{e:?}"); + TrapCode::HeapAccessOutOfBounds + })?; Ok(()) }, )) } - fn gr_reply(ctx: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( + fn gr_reply(ctx: &mut Store, env: &FunctionEnv, memory: Memory) -> Extern { + Extern::Function(Function::new_typed_with_env( ctx, - move |mut caller: Caller<'_, HostState>, ptr: u32, len: i32, _value: i32, _err: i32| { + env, + move |mut env: FunctionEnvMut, + ptr: u32, + len: i32, + _value: i32, + _err: i32| + -> Result<(), TrapCode> { let mut result = vec![0; len as usize]; memory - .read(caller.as_context(), ptr as usize, &mut result) + .view(&env) + .read(ptr as u64, &mut result) .map_err(|e| { log::error!("{:?}", e); - Trap::new(TrapCode::MemoryOutOfBounds.trap_message()) + TrapCode::HeapAccessOutOfBounds })?; - caller.data_mut().msg = result; + env.data_mut().msg = result; Ok(()) }, )) } - fn gr_size(ctx: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( + fn gr_size(ctx: &mut Store, env: &FunctionEnv, memory: Memory) -> Extern { + Extern::Function(Function::new_typed_with_env( ctx, - move |mut caller: Caller<'_, HostState>, size_ptr: u32| { - let size = caller.data().msg.len() as u32; + env, + move |env: FunctionEnvMut, size_ptr: u32| -> Result<(), TrapCode> { + let size = env.data().msg.len() as u32; memory - .clone() - .write( - caller.as_context_mut(), - size_ptr as usize, - &size.to_le_bytes(), - ) + .view(&env) + .write(size_ptr as u64, &size.to_le_bytes()) .map_err(|e| { log::error!("{:?}", e); - Trap::new(TrapCode::MemoryOutOfBounds.trap_message()) + TrapCode::HeapAccessOutOfBounds })?; Ok(()) @@ -281,14 +274,15 @@ mod env { )) } - fn gr_panic(ctx: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( + fn gr_panic(ctx: &mut Store, env: &FunctionEnv, memory: Memory) -> Extern { + Extern::Function(Function::new_typed_with_env( ctx, - move |caller: Caller<'_, HostState>, ptr: u32, len: i32| { + env, + move |env: FunctionEnvMut, ptr: u32, len: i32| -> Result<(), TrapCode> { let mut buff = Vec::with_capacity(len as usize); - memory.read(caller, ptr as usize, &mut buff).map_err(|e| { + memory.view(&env).read(ptr as u64, &mut buff).map_err(|e| { log::error!("{e:?}"); - Trap::new(TrapCode::MemoryOutOfBounds.trap_message()) + TrapCode::HeapAccessOutOfBounds })?; log::error!("Panic: {}", String::from_utf8_lossy(&buff)); @@ -297,8 +291,8 @@ mod env { )) } - fn gr_oom_panic(ctx: impl AsContextMut) -> Extern { - Extern::Func(Func::wrap(ctx, || { + fn gr_oom_panic(ctx: &mut Store) -> Extern { + Extern::Function(Function::new_typed(ctx, || -> Result<(), TrapCode> { log::error!("OOM panic occurred"); Ok(()) })) diff --git a/gcli/src/result.rs b/gcli/src/result.rs index 7b82ef9d6f1..ef4dd244fb5 100644 --- a/gcli/src/result.rs +++ b/gcli/src/result.rs @@ -47,8 +47,8 @@ pub enum Error { Code(gear_core::code::CodeError), #[error("Wasm execution error {0}")] WasmExecution(String), - #[error("Wasmi execution error {0}")] - Wasmi(wasmi::Error), + #[error("Wasmer runtime error {0}")] + Wasmer(wasmer::RuntimeError), #[error(transparent)] Etc(#[from] etc::Error), #[error("Metadata parsing error {0:?}")] diff --git a/sandbox/host/Cargo.toml b/sandbox/host/Cargo.toml index 4032f55c69e..842303c3704 100644 --- a/sandbox/host/Cargo.toml +++ b/sandbox/host/Cargo.toml @@ -20,9 +20,9 @@ defer.workspace = true environmental.workspace = true thiserror.workspace = true log = { workspace = true, features = ["std"] } -sandbox-wasmer.workspace = true -sandbox-wasmer-types.workspace = true -sandbox-wasmi = { workspace = true, features = ["virtual_memory"] } +wasmer = { workspace = true, features = ["singlepass"] } +wasmer-types.workspace = true +sandbox-wasmi.workspace = true sp-allocator = { workspace = true, features = ["std"] } sp-wasm-interface-common = { workspace = true, features = ["std"] } gear-sandbox-env = { workspace = true, features = ["std"] } diff --git a/sandbox/host/src/sandbox.rs b/sandbox/host/src/sandbox.rs index db293e246c7..2efdc0093de 100644 --- a/sandbox/host/src/sandbox.rs +++ b/sandbox/host/src/sandbox.rs @@ -182,7 +182,7 @@ enum BackendInstanceBundle { /// Wasmer module instance and store Wasmer { /// Wasmer module instance - instance: sandbox_wasmer::Instance, + instance: wasmer::Instance, /// Wasmer store store: Rc, }, diff --git a/sandbox/host/src/sandbox/wasmer_backend.rs b/sandbox/host/src/sandbox/wasmer_backend.rs index c92d0beb2ec..a4431947832 100644 --- a/sandbox/host/src/sandbox/wasmer_backend.rs +++ b/sandbox/host/src/sandbox/wasmer_backend.rs @@ -22,9 +22,9 @@ use std::{cell::RefCell, rc::Rc}; use codec::{Decode, Encode}; use gear_sandbox_env::{HostError, Instantiate, WasmReturnValue, GLOBAL_NAME_GAS}; -use sandbox_wasmer::{AsStoreMut, Module, RuntimeError, Store}; -use sandbox_wasmer_types::TrapCode; use sp_wasm_interface_common::{util, Pointer, ReturnValue, Value, WordSize}; +use wasmer::{AsStoreMut, Module, RuntimeError, Store}; +use wasmer_types::TrapCode; use crate::{ error::{Error, Result}, @@ -48,11 +48,11 @@ environmental::environmental!(SupervisorContextStore: trait SupervisorContext); mod store_refcell_ctx { use std::rc::Rc; - use sandbox_wasmer::StoreMut; + use wasmer::StoreMut; use super::{store_refcell::BorrowScopeError, StoreRefCell}; - // We cannot store `StoreRefCell` in `sandbox_wasmer::FunctionEnv` because it doesn't implement Send/Sync, + // We cannot store `StoreRefCell` in `wasmer::FunctionEnv` because it doesn't implement Send/Sync, // so we have to use `environment!` to access it from `dispatch_function` functions. environmental::environmental!(StoreRefCellEnv: Rc); @@ -75,7 +75,7 @@ mod store_refcell_ctx { pub struct Env { // Gas global is optional because it will be initialized after instance creation. // See `instantiate` function. - gas_global: Option, + gas_global: Option, } /// Wasmer specific context @@ -91,9 +91,9 @@ impl Default for Backend { impl Backend { pub fn new() -> Self { - let compiler = sandbox_wasmer::Singlepass::default(); + let compiler = wasmer::Singlepass::default(); Backend { - store: Rc::new(StoreRefCell::new(sandbox_wasmer::Store::new(compiler))), + store: Rc::new(StoreRefCell::new(wasmer::Store::new(compiler))), } } @@ -104,7 +104,7 @@ impl Backend { /// Invoke a function within a sandboxed module pub fn invoke( - instance: &sandbox_wasmer::Instance, + instance: &wasmer::Instance, store: &Rc, export_name: &str, args: &[Value], @@ -115,7 +115,7 @@ pub fn invoke( .get_function(export_name) .map_err(|error| Error::Sandbox(error.to_string()))?; - let args: Vec = args.iter().map(into_wasmer_val).collect(); + let args: Vec = args.iter().map(into_wasmer_val).collect(); let wasmer_result = SupervisorContextStore::using(supervisor_context, || { store_refcell_ctx::using(&mut store.clone(), || { @@ -190,19 +190,17 @@ pub fn instantiate( let module = Module::new(&context.store().borrow(), wasm) .map_err(|_| InstantiationError::ModuleDecoding)?; - let mut exports = sandbox_wasmer::Exports::new(); + let mut exports = wasmer::Exports::new(); - let func_env = sandbox_wasmer::FunctionEnv::new( - &mut context.store().borrow_mut(), - Env { gas_global: None }, - ); + let func_env = + wasmer::FunctionEnv::new(&mut context.store().borrow_mut(), Env { gas_global: None }); for import in module.imports() { match import.ty() { // Nothing to do here - sandbox_wasmer::ExternType::Global(_) | sandbox_wasmer::ExternType::Table(_) => (), + wasmer::ExternType::Global(_) | wasmer::ExternType::Table(_) => (), - sandbox_wasmer::ExternType::Memory(_) => { + wasmer::ExternType::Memory(_) => { let memory = guest_env .imports .memory_by_name(import.module(), import.name()) @@ -229,10 +227,10 @@ pub fn instantiate( .map_err(|_| InstantiationError::EnvironmentDefinitionCorrupted)? .clone(); - exports.insert(import.name(), sandbox_wasmer::Extern::Memory(wasmer_memory)); + exports.insert(import.name(), wasmer::Extern::Memory(wasmer_memory)); } - sandbox_wasmer::ExternType::Function(func_ty) => { + wasmer::ExternType::Function(func_ty) => { let guest_func_index = guest_env .imports .func_by_name(import.module(), import.name()); @@ -264,35 +262,30 @@ pub fn instantiate( ), }; - exports.insert(import.name(), sandbox_wasmer::Extern::Function(function)); + exports.insert(import.name(), wasmer::Extern::Function(function)); } } } - let mut import_object = sandbox_wasmer::Imports::new(); + let mut import_object = wasmer::Imports::new(); import_object.register_namespace("env", exports); let instance = SupervisorContextStore::using(supervisor_context, || { - sandbox_wasmer::Instance::new(&mut context.store().borrow_mut(), &module, &import_object) - .map_err(|error| { - log::trace!("Failed to call sandbox_wasmer::Instance::new: {error:?}"); + wasmer::Instance::new(&mut context.store().borrow_mut(), &module, &import_object).map_err( + |error| { + log::trace!("Failed to call wasmer::Instance::new: {error:?}"); match error { - sandbox_wasmer::InstantiationError::Link(_) => { - InstantiationError::Instantiation - } - sandbox_wasmer::InstantiationError::Start(_) => { - InstantiationError::StartTrapped - } - sandbox_wasmer::InstantiationError::CpuFeature(_) => { - InstantiationError::CpuFeature - } - sandbox_wasmer::InstantiationError::DifferentStores - | sandbox_wasmer::InstantiationError::DifferentArchOS => { + wasmer::InstantiationError::Link(_) => InstantiationError::Instantiation, + wasmer::InstantiationError::Start(_) => InstantiationError::StartTrapped, + wasmer::InstantiationError::CpuFeature(_) => InstantiationError::CpuFeature, + wasmer::InstantiationError::DifferentStores + | wasmer::InstantiationError::DifferentArchOS => { InstantiationError::EnvironmentDefinitionCorrupted } } - }) + }, + ) })?; // Initialize function environment with gas global after instance creation. @@ -379,28 +372,28 @@ fn dispatch_common( serialized_result_val } -fn into_wasmer_val(value: &Value) -> sandbox_wasmer::Value { +fn into_wasmer_val(value: &Value) -> wasmer::Value { match value { - Value::I32(val) => sandbox_wasmer::Value::I32(*val), - Value::I64(val) => sandbox_wasmer::Value::I64(*val), - Value::F32(val) => sandbox_wasmer::Value::F32(f32::from_bits(*val)), - Value::F64(val) => sandbox_wasmer::Value::F64(f64::from_bits(*val)), + Value::I32(val) => wasmer::Value::I32(*val), + Value::I64(val) => wasmer::Value::I64(*val), + Value::F32(val) => wasmer::Value::F32(f32::from_bits(*val)), + Value::F64(val) => wasmer::Value::F64(f64::from_bits(*val)), } } -fn into_wasmer_result(value: ReturnValue) -> Vec { +fn into_wasmer_result(value: ReturnValue) -> Vec { match value { ReturnValue::Value(v) => vec![into_wasmer_val(&v)], ReturnValue::Unit => vec![], } } -fn into_value(value: &sandbox_wasmer::Value) -> Option { +fn into_value(value: &wasmer::Value) -> Option { match value { - sandbox_wasmer::Value::I32(val) => Some(Value::I32(*val)), - sandbox_wasmer::Value::I64(val) => Some(Value::I64(*val)), - sandbox_wasmer::Value::F32(val) => Some(Value::F32(f32::to_bits(*val))), - sandbox_wasmer::Value::F64(val) => Some(Value::F64(f64::to_bits(*val))), + wasmer::Value::I32(val) => Some(Value::I32(*val)), + wasmer::Value::I64(val) => Some(Value::I64(*val)), + wasmer::Value::F32(val) => Some(Value::F32(f32::to_bits(*val))), + wasmer::Value::F64(val) => Some(Value::F64(f64::to_bits(*val))), _ => None, } } @@ -408,10 +401,10 @@ fn into_value(value: &sandbox_wasmer::Value) -> Option { fn dispatch_function( supervisor_func_index: SupervisorFuncIndex, store: &mut Store, - func_env: &sandbox_wasmer::FunctionEnv, - func_ty: &sandbox_wasmer::FunctionType, -) -> sandbox_wasmer::Function { - sandbox_wasmer::Function::new_with_env(store, func_env, func_ty, move |mut env, params| { + func_env: &wasmer::FunctionEnv, + func_ty: &wasmer::FunctionType, +) -> wasmer::Function { + wasmer::Function::new_with_env(store, func_env, func_ty, move |mut env, params| { SupervisorContextStore::with(|supervisor_context| { let mut storemut = env.as_store_mut(); @@ -451,10 +444,10 @@ fn dispatch_function( fn dispatch_function_v2( supervisor_func_index: SupervisorFuncIndex, store: &mut Store, - func_env: &sandbox_wasmer::FunctionEnv, - func_ty: &sandbox_wasmer::FunctionType, -) -> sandbox_wasmer::Function { - sandbox_wasmer::Function::new_with_env(store, func_env, func_ty, move |mut env, params| { + func_env: &wasmer::FunctionEnv, + func_ty: &wasmer::FunctionType, +) -> wasmer::Function { + wasmer::Function::new_with_env(store, func_env, func_ty, move |mut env, params| { SupervisorContextStore::with(|supervisor_context| { let (env, mut storemut) = env.data_and_store_mut(); let gas_global = env @@ -494,10 +487,7 @@ fn dispatch_function_v2( .map_err(|_| RuntimeError::new("StoreRefCell borrow scope error"))??; gas_global - .set( - &mut storemut, - sandbox_wasmer::Value::I64(deserialized_result.gas), - ) + .set(&mut storemut, wasmer::Value::I64(deserialized_result.gas)) .map_err(|_| RuntimeError::new("Cannot set gas global from store environment"))?; Ok(into_wasmer_result(deserialized_result.inner)) @@ -512,8 +502,8 @@ pub fn new_memory( initial: u32, maximum: Option, ) -> crate::error::Result { - let ty = sandbox_wasmer::MemoryType::new(initial, maximum, false); - let memory = sandbox_wasmer::Memory::new(&mut store.borrow_mut(), ty) + let ty = wasmer::MemoryType::new(initial, maximum, false); + let memory = wasmer::Memory::new(&mut store.borrow_mut(), ty) .map_err(|_| Error::InvalidMemoryReference)?; Ok(Memory::Wasmer(MemoryWrapper::new(memory, store))) @@ -523,13 +513,13 @@ pub fn new_memory( /// we wrap it with `RefCell` and encapsulate all memory operations. #[derive(Debug, Clone)] pub struct MemoryWrapper { - buffer: Rc>, + buffer: Rc>, store: Rc, } impl MemoryWrapper { /// Take ownership of the memory region and return a wrapper object - pub fn new(memory: sandbox_wasmer::Memory, store: Rc) -> Self { + pub fn new(memory: wasmer::Memory, store: Rc) -> Self { Self { buffer: Rc::new(RefCell::new(memory)), store, @@ -543,10 +533,7 @@ impl MemoryWrapper { /// Wasmer doesn't provide comprehensive documentation about the exact behavior of the data /// pointer. If a dynamic style heap is used the base pointer of the heap can change. Since /// growing, we cannot guarantee the lifetime of the returned slice reference. - unsafe fn memory_as_slice<'m>( - memory: &'m sandbox_wasmer::Memory, - store: &sandbox_wasmer::Store, - ) -> &'m [u8] { + unsafe fn memory_as_slice<'m>(memory: &'m wasmer::Memory, store: &wasmer::Store) -> &'m [u8] { let memory_view = memory.view(store); let ptr = memory_view.data_ptr() as *const _; @@ -571,8 +558,8 @@ impl MemoryWrapper { /// returned it must be ensured that only one mutable and no shared references to memory /// exists at the same time. unsafe fn memory_as_slice_mut<'m>( - memory: &'m mut sandbox_wasmer::Memory, - store: &sandbox_wasmer::Store, + memory: &'m mut wasmer::Memory, + store: &wasmer::Store, ) -> &'m mut [u8] { let memory_view = memory.view(store); let ptr = memory_view.data_ptr(); @@ -672,8 +659,8 @@ impl MemoryTransfer for MemoryWrapper { /// Get global value by name pub fn get_global( - instance: &sandbox_wasmer::Instance, - store: &mut sandbox_wasmer::Store, + instance: &wasmer::Instance, + store: &mut wasmer::Store, name: &str, ) -> Option { let global = instance.exports.get_global(name).ok()?; @@ -683,8 +670,8 @@ pub fn get_global( /// Set global value by name pub fn set_global( - instance: &sandbox_wasmer::Instance, - mut store: &mut sandbox_wasmer::Store, + instance: &wasmer::Instance, + mut store: &mut wasmer::Store, name: &str, value: Value, ) -> core::result::Result, crate::error::Error> { diff --git a/sandbox/host/src/sandbox/wasmer_backend/cache.rs b/sandbox/host/src/sandbox/wasmer_backend/cache.rs index cce61adcac4..e7089cfb151 100644 --- a/sandbox/host/src/sandbox/wasmer_backend/cache.rs +++ b/sandbox/host/src/sandbox/wasmer_backend/cache.rs @@ -25,9 +25,9 @@ use std::{ sync::{Mutex, OnceLock}, }; -use sandbox_wasmer::Module; use tempfile::TempDir; use uluru::LRUCache; +use wasmer::Module; use wasmer_cache::Hash; pub struct CacheMissErr { @@ -65,10 +65,7 @@ fn fs_cache() -> FileSystemCache { FileSystemCache::new(cache_path) } -pub fn get_cached_module( - wasm: &[u8], - store: &sandbox_wasmer::Store, -) -> Result { +pub fn get_cached_module(wasm: &[u8], store: &wasmer::Store) -> Result { let mut lru_lock = lru_cache().lock().expect("CACHED_MODULES lock fail"); let maybe_module = lru_lock.find(|x| x.wasm == wasm); diff --git a/sandbox/host/src/sandbox/wasmer_backend/store_refcell.rs b/sandbox/host/src/sandbox/wasmer_backend/store_refcell.rs index ec6193242df..58f73a14552 100644 --- a/sandbox/host/src/sandbox/wasmer_backend/store_refcell.rs +++ b/sandbox/host/src/sandbox/wasmer_backend/store_refcell.rs @@ -18,7 +18,7 @@ //! # Description //! -//! Custom implementation of `RefCell` for the `sandbox_wasmer::Store` type, +//! Custom implementation of `RefCell` for the `wasmer::Store` type, //! enabling safe repeated mutable borrowing of `StoreRefCell` higher up the call stack //! when the mutable borrow of `StoreRefCell` still exists. //! @@ -92,7 +92,7 @@ use std::{ }; use defer::defer; -use sandbox_wasmer::{AsStoreMut, AsStoreRef, Store, StoreRef}; +use wasmer::{AsStoreMut, AsStoreRef, Store, StoreRef}; #[derive(Debug, Clone, Copy)] enum BorrowState { @@ -281,7 +281,7 @@ impl Drop for RefMut<'_> { mod tests { use std::rc::Rc; - use sandbox_wasmer::StoreMut; + use wasmer::StoreMut; use super::*; diff --git a/utils/calc-stack-height/Cargo.toml b/utils/calc-stack-height/Cargo.toml index 7160847d783..31faf729ae3 100644 --- a/utils/calc-stack-height/Cargo.toml +++ b/utils/calc-stack-height/Cargo.toml @@ -11,8 +11,8 @@ repository.workspace = true gear-core.workspace = true gear-wasm-instrument.workspace = true vara-runtime = { workspace = true, features = ["std", "dev"] } -sandbox-wasmer.workspace = true -sandbox-wasmer-types.workspace = true +wasmer = { workspace = true, features = ["singlepass"] } +wasmer-types.workspace = true log.workspace = true env_logger.workspace = true wabt.workspace = true diff --git a/utils/calc-stack-height/src/main.rs b/utils/calc-stack-height/src/main.rs index 5d48e1252bf..ae626187f52 100644 --- a/utils/calc-stack-height/src/main.rs +++ b/utils/calc-stack-height/src/main.rs @@ -1,11 +1,11 @@ use gear_core::code::{Code, TryNewCodeConfig}; use gear_wasm_instrument::{SystemBreakCode, STACK_HEIGHT_EXPORT_NAME}; -use sandbox_wasmer::{ +use std::{env, fs}; +use wasmer::{ Exports, Extern, Function, FunctionEnv, Imports, Instance, Memory, MemoryType, Module, RuntimeError, Singlepass, Store, }; -use sandbox_wasmer_types::{FunctionType, TrapCode, Type}; -use std::{env, fs}; +use wasmer_types::{FunctionType, TrapCode, Type}; fn main() -> anyhow::Result<()> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); diff --git a/utils/crates-io/src/handler.rs b/utils/crates-io/src/handler.rs index d79d69ef357..bf3c23ff203 100644 --- a/utils/crates-io/src/handler.rs +++ b/utils/crates-io/src/handler.rs @@ -82,11 +82,6 @@ pub fn patch_workspace(name: &str, table: &mut toml_edit::InlineTable) { // // issue: https://github.com/rust-lang/cargo/issues/4242 fn trim_dev_dep(name: &str, manifest: &mut DocumentMut) { - if let Some(dep) = manifest["dev-dependencies"][name].as_inline_table_mut() { - dep.remove("workspace"); - dep.insert("version", "~1".into()); - } - if let Some(dep) = manifest["dev-dependencies"][name].as_table_like_mut() { dep.remove("workspace"); dep.insert("version", toml_edit::value("~1")); @@ -151,11 +146,11 @@ mod sandbox { /// Replace the wasmi module to the crates-io version. pub fn patch(manifest: &mut DocumentMut) { - let Some(wasmi) = manifest["dependencies"]["wasmi"].as_inline_table_mut() else { + let Some(wasmi) = manifest["dependencies"]["wasmi"].as_table_like_mut() else { return; }; - wasmi.insert("package", "gwasmi".into()); - wasmi.insert("version", "0.30.0".into()); + wasmi.insert("package", toml_edit::value("gwasmi")); + wasmi.insert("version", toml_edit::value("0.30.0")); wasmi.remove("branch"); wasmi.remove("git"); } @@ -172,7 +167,7 @@ mod sandbox_interface { /// `sp_runtime_interface_proc_macro` includes some hardcode /// that could not locate alias packages. pub fn patch(manifest: &mut DocumentMut) { - let Some(wi) = manifest["dependencies"]["sp-runtime-interface"].as_table_mut() else { + let Some(wi) = manifest["dependencies"]["sp-runtime-interface"].as_table_like_mut() else { return; }; wi.insert("version", toml_edit::value(GP_RUNTIME_INTERFACE_VERSION)); @@ -187,11 +182,11 @@ mod sandbox_host { /// Replace the wasmi module to the crates-io version. pub fn patch(manifest: &mut DocumentMut) { - let Some(wasmi) = manifest["dependencies"]["sandbox-wasmi"].as_inline_table_mut() else { + let Some(wasmi) = manifest["dependencies"]["sandbox-wasmi"].as_table_like_mut() else { return; }; - wasmi.insert("package", "wasmi".into()); - wasmi.insert("version", "0.13.2".into()); + wasmi.insert("package", toml_edit::value("wasmi")); + wasmi.insert("version", toml_edit::value("0.13.2")); wasmi.remove("workspace"); } } diff --git a/utils/crates-io/src/manifest.rs b/utils/crates-io/src/manifest.rs index d358e93cc3e..3e72febdbff 100644 --- a/utils/crates-io/src/manifest.rs +++ b/utils/crates-io/src/manifest.rs @@ -99,7 +99,8 @@ impl Workspace { .ok_or_else(|| anyhow!("Could not find version in workspace manifest"))? .to_string(); - let Some(deps) = self.mutable_manifest["workspace"]["dependencies"].as_table_mut() else { + let Some(deps) = self.mutable_manifest["workspace"]["dependencies"].as_table_like_mut() + else { return Err(anyhow!( "Failed to parse dependencies from workspace {}", self.path.display() diff --git a/utils/lazy-pages-fuzzer/Cargo.toml b/utils/lazy-pages-fuzzer/Cargo.toml index d602ef5bc6b..ced04890460 100644 --- a/utils/lazy-pages-fuzzer/Cargo.toml +++ b/utils/lazy-pages-fuzzer/Cargo.toml @@ -14,7 +14,7 @@ gear-lazy-pages.workspace = true gear-lazy-pages-common.workspace = true log.workspace = true region.workspace = true -sandbox-wasmer.workspace = true +wasmer = { workspace = true, features = ["singlepass"] } sandbox-wasmi.workspace = true wasmprinter.workspace = true wat.workspace = true diff --git a/utils/lazy-pages-fuzzer/src/wasmer_backend.rs b/utils/lazy-pages-fuzzer/src/wasmer_backend.rs index bafd1f25818..b12ae31f233 100644 --- a/utils/lazy-pages-fuzzer/src/wasmer_backend.rs +++ b/utils/lazy-pages-fuzzer/src/wasmer_backend.rs @@ -20,7 +20,7 @@ use anyhow::{bail, Context, Result}; use gear_wasm_gen::SyscallName; use gear_wasm_instrument::{parity_wasm::elements::Module, GLOBAL_NAME_GAS}; -use sandbox_wasmer::{ +use wasmer::{ Exports, Extern, Function, FunctionType, Imports, Instance, Memory, MemoryType, Module as WasmerModule, RuntimeError, Singlepass, Store, Type, Value, }; diff --git a/utils/wasm-builder/Cargo.toml b/utils/wasm-builder/Cargo.toml index 525a53b9fc3..d11bb245d3d 100644 --- a/utils/wasm-builder/Cargo.toml +++ b/utils/wasm-builder/Cargo.toml @@ -29,7 +29,6 @@ itertools.workspace = true [dev-dependencies] wabt.workspace = true -wasmi = { workspace = true, features = ["std"] } parity-wasm.workspace = true [features] diff --git a/utils/wasm-optimizer/Cargo.toml b/utils/wasm-optimizer/Cargo.toml index 581ac2ad319..0501a8c94dd 100644 --- a/utils/wasm-optimizer/Cargo.toml +++ b/utils/wasm-optimizer/Cargo.toml @@ -23,5 +23,5 @@ which.workspace = true colored.workspace = true [dev-dependencies] -wasmi = { workspace = true, features = ["std"] } +wasmer = { workspace = true, features = ["std"] } wabt.workspace = true diff --git a/utils/wasm-optimizer/src/stack_end.rs b/utils/wasm-optimizer/src/stack_end.rs index 28abc2773ed..414ab0837d7 100644 --- a/utils/wasm-optimizer/src/stack_end.rs +++ b/utils/wasm-optimizer/src/stack_end.rs @@ -386,7 +386,7 @@ mod test { }; use pwasm_utils::parity_wasm; use wabt::Wat2Wasm; - use wasmi::{core::Value, Engine, Linker, Memory, MemoryType, Store}; + use wasmer::{Imports, Instance, Memory, MemoryType, Module, Store, Value}; #[test] fn assembly_script_stack_pointer() { @@ -452,20 +452,15 @@ mod test { .expect("failed to parse module"); let check = |binary, expected| { - let mut store: Store<()> = Store::new(&Engine::default(), ()); - let mut linker: Linker<()> = Linker::new(); - let module = wasmi::Module::new(store.engine(), binary).unwrap(); - let mut outputs = [Value::I32(-1)]; - linker - .instantiate(&mut store, &module) - .unwrap() - .ensure_no_start(&mut store) - .unwrap() - .get_export(&store, "handle") - .unwrap() - .into_func() + let mut store: Store = Store::default(); + let module = Module::new(store.engine(), binary).unwrap(); + let instance = Instance::new(&mut store, &module, &Imports::new()).unwrap(); + + let outputs = instance + .exports + .get_function("handle") .unwrap() - .call(&mut store, &[Value::I32(1)], &mut outputs) + .call(&mut store, &[Value::I32(1)]) .unwrap(); assert_eq!(outputs[0], Value::I32(expected)); }; @@ -509,41 +504,33 @@ mod test { .expect("failed to parse module"); let check = |binary, expected1, expected2| { - let mut store: Store<()> = Store::new(&Engine::default(), ()); - let module = wasmi::Module::new(store.engine(), binary).unwrap(); - let memory = Memory::new(&mut store, MemoryType::new(1, None)).unwrap(); - - let mut linker: Linker<()> = Linker::new(); - linker.define("env", "memory", memory).unwrap(); - - let mut outputs = [Value::I32(-1)]; - linker - .instantiate(&mut store, &module) + let mut store: Store = Store::default(); + let module = Module::new(store.engine(), binary).unwrap(); + let memory = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap(); + let imports = wasmer::imports! { + "env" => { + "memory" => memory.clone(), + } + }; + let instance = Instance::new(&mut store, &module, &imports).unwrap(); + + let outputs = instance + .exports + .get_function("handle") .unwrap() - .ensure_no_start(&mut store) - .unwrap() - .get_export(&store, "handle") - .unwrap() - .into_func() - .unwrap() - .call(&mut store, &[Value::I32(1)], &mut outputs) + .call(&mut store, &[Value::I32(1)]) .unwrap(); assert_eq!(outputs[0], Value::I32(expected1)); let mut data = vec![0u8; 0x10000]; - memory.read(&store, 0, data.as_mut_slice()).unwrap(); - let instance = linker - .instantiate(&mut store, &module) - .unwrap() - .ensure_no_start(&mut store) - .unwrap(); - memory.write(&mut store, 0, &data).unwrap(); - instance - .get_export(&store, "handle") - .unwrap() - .into_func() + memory.view(&store).read(0, data.as_mut_slice()).unwrap(); + let instance = Instance::new(&mut store, &module, &imports).unwrap(); + memory.view(&store).write(0, &data).unwrap(); + let outputs = instance + .exports + .get_function("handle") .unwrap() - .call(&mut store, &[Value::I32(1)], &mut outputs) + .call(&mut store, &[Value::I32(1)]) .unwrap(); assert_eq!(outputs[0], Value::I32(expected2)); };