Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wasmer 3 follow up #1693

Merged
merged 8 commits into from
May 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ and this project adheres to
- cosmwasm-vm: Add `Instance::set_debug_handler`/`unset_debug_handler` to allow
customizing the handling of debug messages emitted by the contract ([#1667]).
- cosmwasm-vm: Add `.wasm` extension to stored wasm files ([#1686]).
- cosmwasm-vm: Upgrade Wasmer to version 3.3.0.
- cosmwasm-check: Update clap dependency to version 4 ([#1677])

[#1511]: https://github.com/CosmWasm/cosmwasm/issues/1511
Expand Down
12 changes: 7 additions & 5 deletions packages/vm/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,12 @@ where

/// Pins a Module that was previously stored via save_wasm.
///
/// The module is lookup first in the memory cache, and then in the file system cache.
/// If not found, the code is loaded from the file system, compiled, and stored into the
/// The module is lookup first in the file system cache. If not found,
/// the code is loaded from the file system, compiled, and stored into the
/// pinned cache.
/// If the given ID is not found, or the content does not match the hash (=ID), an error is returned.
///
/// If the given contract for the given checksum is not found, or the content
/// does not match the checksum, an error is returned.
pub fn pin(&self, checksum: &Checksum) -> VmResult<()> {
let mut cache = self.inner.lock().unwrap();
if cache.pinned_memory_cache.has(checksum) {
Expand All @@ -255,7 +257,7 @@ where

// We don't load from the memory cache because we had to create new store here and
// serialize/deserialize the artifact to get a full clone. Could be done but adds some code
// for a no-so-relevant use case.
// for a not-so-relevant use case.

// Try to get module from file system cache
let engine = Engine::headless();
Expand Down Expand Up @@ -730,7 +732,7 @@ mod tests {
let backend5 = mock_backend(&[]);

// from file system
let _instance1: Instance<MockApi, MockStorage, MockQuerier> = cache
let _instance1 = cache
.get_instance(&checksum, backend1, TESTING_OPTIONS)
.unwrap();
assert_eq!(cache.stats().hits_pinned_memory_cache, 0);
Expand Down
14 changes: 14 additions & 0 deletions packages/vm/src/errors/communication_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::fmt::Debug;
use thiserror::Error;

use super::region_validation_error::RegionValidationError;
use crate::memory::Region;

/// An error in the communcation between contract and host. Those happen around imports and exports.
#[derive(Error, Debug)]
Expand Down Expand Up @@ -32,6 +33,12 @@ pub enum CommunicationError {
RegionLengthTooBig { length: usize, max_length: usize },
#[error("Region too small. Got {}, required {}", size, required)]
RegionTooSmall { size: usize, required: usize },
#[error("Tried to access memory of region {:?} in Wasm memory of size {} bytes. This typically happens when the given Region pointer does not point to a proper Region struct.", region, memory_size)]
RegionAccessErr {
region: Region,
/// Current size of the linear memory in bytes
memory_size: usize,
},
#[error("Got a zero Wasm address")]
ZeroAddress {},
}
Expand Down Expand Up @@ -64,6 +71,13 @@ impl CommunicationError {
CommunicationError::RegionTooSmall { size, required }
}

pub(crate) fn region_access_err(region: Region, memory_size: usize) -> Self {
CommunicationError::RegionAccessErr {
region,
memory_size,
}
}

pub(crate) fn zero_address() -> Self {
CommunicationError::ZeroAddress {}
}
Expand Down
16 changes: 9 additions & 7 deletions packages/vm/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,18 +602,21 @@ mod tests {
let (engine, module) = compile(&wasm, &[]).unwrap();
let mut store = make_store_with_engine(engine, memory_limit);

let called = Arc::new(AtomicBool::new(false));

#[derive(Clone)]
struct MyEnv {
// This can be mutated across threads safely. We initialize it as `false`
// and let our imported fn switch it to `true` to confirm it works.
called: Arc<AtomicBool>,
}

let my_env = MyEnv {
called: Arc::new(AtomicBool::new(false)),
};

let fe = FunctionEnv::new(&mut store, my_env);
let fe = FunctionEnv::new(
&mut store,
MyEnv {
called: called.clone(),
},
);

let fun =
Function::new_typed_with_env(&mut store, &fe, move |fe_mut: FunctionEnvMut<MyEnv>| {
Expand All @@ -636,8 +639,7 @@ mod tests {

instance.call_function0("main", &[]).unwrap();

// TODO: allow inspecting env
// assert!(fe.as_ref(&store).called.load(Ordering::Relaxed));
assert!(called.load(Ordering::Relaxed));
}

#[test]
Expand Down
39 changes: 15 additions & 24 deletions packages/vm/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::errors::{
/// but defined here to allow Wasmer specific implementation.
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
struct Region {
pub struct Region {
/// The beginning of the region expressed as bytes from the beginning of the linear memory
pub offset: u32,
/// The number of bytes available in this region
Expand Down Expand Up @@ -47,12 +47,9 @@ pub fn read_region(memory: &wasmer::MemoryView, ptr: u32, max_length: usize) ->
}

let mut result = vec![0u8; region.length as usize];
// TODO: double check error handling
memory.read(region.offset as u64, &mut result).map_err(|_err| CommunicationError::deref_err(region.offset, format!(
"Tried to access memory of region {:?} in wasm memory of size {} bytes. This typically happens when the given Region pointer does not point to a proper Region struct.",
region,
memory.size().bytes().0
)))?;
memory
.read(region.offset as u64, &mut result)
.map_err(|_err| CommunicationError::region_access_err(region, memory.size().bytes().0))?;
Ok(result)
}

Expand Down Expand Up @@ -82,25 +79,21 @@ pub fn write_region(memory: &wasmer::MemoryView, ptr: u32, data: &[u8]) -> VmRes
return Err(CommunicationError::region_too_small(region_capacity, data.len()).into());
}

// TODO: double check error handling
memory.write(region.offset as u64, data).map_err(|_err| CommunicationError::deref_err(region.offset, format!(
"Tried to access memory of region {:?} in wasm memory of size {} bytes. This typically happens when the given Region pointer does not point to a proper Region struct.",
region,
memory.size().bytes().0
)))?;
memory
.write(region.offset as u64, data)
.map_err(|_err| CommunicationError::region_access_err(region, memory.size().bytes().0))?;

region.length = data.len() as u32;
set_region(memory, ptr, region)?;

Ok(())
}

/// Reads in a Region at ptr in wasm memory and returns a copy of it
fn get_region(memory: &wasmer::MemoryView, ptr: u32) -> CommunicationResult<Region> {
let wptr = WasmPtr::<Region>::new(ptr);
// TODO: double check error handling
/// Reads in a Region at offset in Wasm memory and returns a copy of it
fn get_region(memory: &wasmer::MemoryView, offset: u32) -> CommunicationResult<Region> {
let wptr = WasmPtr::<Region>::new(offset);
let region = wptr.deref(memory).read().map_err(|_err| {
CommunicationError::deref_err(ptr, "Could not dereference this pointer to a Region")
CommunicationError::deref_err(offset, "Could not dereference this pointer to a Region")
})?;
validate_region(&region)?;
Ok(region)
Expand All @@ -127,13 +120,11 @@ fn validate_region(region: &Region) -> RegionValidationResult<()> {
Ok(())
}

/// Overrides a Region at ptr in wasm memory with data
fn set_region(memory: &wasmer::MemoryView, ptr: u32, data: Region) -> CommunicationResult<()> {
let wptr = WasmPtr::<Region>::new(ptr);

// TODO: double check error handling
/// Overrides a Region at offset in Wasm memory
fn set_region(memory: &wasmer::MemoryView, offset: u32, data: Region) -> CommunicationResult<()> {
let wptr = WasmPtr::<Region>::new(offset);
wptr.deref(memory).write(data).map_err(|_err| {
CommunicationError::deref_err(ptr, "Could not dereference this pointer to a Region")
CommunicationError::deref_err(offset, "Could not dereference this pointer to a Region")
})?;
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion packages/vm/src/modules/in_memory_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::hash_map::RandomState;
use std::num::NonZeroUsize;
use wasmer::{Engine, Module};

use super::sized_module::CachedModule;
use super::cached_module::CachedModule;
use crate::{Checksum, Size, VmError, VmResult};

// Minimum module size.
Expand Down
4 changes: 2 additions & 2 deletions packages/vm/src/modules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
mod cached_module;
mod file_system_cache;
mod in_memory_cache;
mod pinned_memory_cache;
mod sized_module;
mod versioning;

pub use cached_module::CachedModule;
pub use file_system_cache::{FileSystemCache, NewFileSystemCacheError};
pub use in_memory_cache::InMemoryCache;
pub use pinned_memory_cache::PinnedMemoryCache;
pub use sized_module::CachedModule;
pub use versioning::current_wasmer_module_version;
2 changes: 1 addition & 1 deletion packages/vm/src/modules/pinned_memory_cache.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;
use wasmer::{Engine, Module};

use super::sized_module::CachedModule;
use super::cached_module::CachedModule;
use crate::{Checksum, VmResult};

/// An pinned in memory module cache
Expand Down
25 changes: 8 additions & 17 deletions packages/vm/src/wasm_backend/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,17 @@ pub fn make_engine(middlewares: &[Arc<dyn ModuleMiddleware>]) -> Engine {
let metering = Arc::new(Metering::new(gas_limit, cost));

#[cfg(feature = "cranelift")]
{
let mut compiler = Cranelift::default();
for middleware in middlewares {
compiler.push_middleware(middleware.clone());
}
compiler.push_middleware(deterministic);
compiler.push_middleware(metering);
compiler.into()
}
let mut compiler = Cranelift::default();

#[cfg(not(feature = "cranelift"))]
{
let mut compiler = Singlepass::default();
for middleware in middlewares {
compiler.push_middleware(middleware.clone());
}
compiler.push_middleware(deterministic);
compiler.push_middleware(metering);
compiler.into()
let mut compiler = Singlepass::default();

for middleware in middlewares {
compiler.push_middleware(middleware.clone());
}
compiler.push_middleware(deterministic);
compiler.push_middleware(metering);
compiler.into()
}

/// Created a store with no compiler and the given memory limit (in bytes)
Expand Down