Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Bump wasmtime to 5.0.0 (and a few other deps) (#13160)
Browse files Browse the repository at this point in the history
* Bump `wasmtime` to 4.0.0 (and a few other deps)

* Use `Error::msg` instead of `anyhow!`

* Bump `wasmtime` to 5.0.0

* Update `Cargo.lock`

* Add `wasmtime` feature to `sp-wasm-interface` dependency
  • Loading branch information
koute committed Feb 6, 2023
1 parent 51cf2e7 commit 47ecdb6
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 142 deletions.
159 changes: 74 additions & 85 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions client/executor/wasmtime/Cargo.toml
Expand Up @@ -19,26 +19,26 @@ log = "0.4.17"

# When bumping wasmtime do not forget to also bump rustix
# to exactly the same version as used by wasmtime!
wasmtime = { version = "1.0.0", default-features = false, features = [
wasmtime = { version = "5.0.0", default-features = false, features = [
"cache",
"cranelift",
"jitdump",
"parallel-compilation",
"memory-init-cow",
"pooling-allocator",
"pooling-allocator"
] }
anyhow = "1.0.68"
sc-allocator = { version = "4.1.0-dev", path = "../../allocator" }
sc-executor-common = { version = "0.10.0-dev", path = "../common" }
sp-runtime-interface = { version = "7.0.0", path = "../../../primitives/runtime-interface" }
sp-wasm-interface = { version = "7.0.0", path = "../../../primitives/wasm-interface" }
sp-wasm-interface = { version = "7.0.0", path = "../../../primitives/wasm-interface", features = ["wasmtime"] }

# Here we include the rustix crate in the exactly same semver-compatible version as used by
# wasmtime and enable its 'use-libc' flag.
#
# By default rustix directly calls the appropriate syscalls completely bypassing libc;
# this doesn't have any actual benefits for us besides making it harder to debug memory
# problems (since then `mmap` etc. cannot be easily hooked into).
rustix = { version = "0.35.9", default-features = false, features = ["std", "mm", "fs", "param", "use-libc"] }
rustix = { version = "0.36.0", default-features = false, features = ["std", "mm", "fs", "param", "use-libc"] }
once_cell = "1.12.0"

[dev-dependencies]
Expand All @@ -48,3 +48,4 @@ sp-io = { version = "7.0.0", path = "../../../primitives/io" }
tempfile = "3.3.0"
paste = "1.0"
codec = { package = "parity-scale-codec", version = "3.2.2" }
cargo_metadata = "0.15.2"
4 changes: 2 additions & 2 deletions client/executor/wasmtime/src/imports.rs
Expand Up @@ -20,7 +20,7 @@ use crate::{host::HostContext, runtime::StoreData};
use sc_executor_common::error::WasmError;
use sp_wasm_interface::{FunctionContext, HostFunctions};
use std::collections::HashMap;
use wasmtime::{ExternType, FuncType, ImportType, Linker, Module, Trap};
use wasmtime::{ExternType, FuncType, ImportType, Linker, Module};

/// Goes over all imports of a module and prepares the given linker for instantiation of the module.
/// Returns an error if there are imports that cannot be satisfied.
Expand Down Expand Up @@ -67,7 +67,7 @@ where
log::debug!("Missing import: '{}' {:?}", name, func_ty);
linker
.func_new("env", &name, func_ty.clone(), move |_, _, _| {
Err(Trap::new(error.clone()))
Err(anyhow::Error::msg(error.clone()))
})
.expect("adding a missing import stub can only fail when the item already exists, and it is missing here; qed");
}
Expand Down
34 changes: 12 additions & 22 deletions client/executor/wasmtime/src/instance_wrapper.rs
Expand Up @@ -76,27 +76,17 @@ impl EntryPoint {
.as_mut()
.expect("host state cannot be empty while a function is being called; qed");

// The logic to print out a backtrace is somewhat complicated,
// so let's get wasmtime to print it out for us.
let mut backtrace_string = trap.to_string();
let suffix = "\nwasm backtrace:";
if let Some(index) = backtrace_string.find(suffix) {
// Get rid of the error message and just grab the backtrace,
// since we're storing the error message ourselves separately.
backtrace_string.replace_range(0..index + suffix.len(), "");
}

let backtrace = Backtrace { backtrace_string };
if let Some(error) = host_state.take_panic_message() {
Error::AbortedDueToPanic(MessageWithBacktrace {
message: error,
backtrace: Some(backtrace),
})
let backtrace = trap.downcast_ref::<wasmtime::WasmBacktrace>().map(|backtrace| {
// The logic to print out a backtrace is somewhat complicated,
// so let's get wasmtime to print it out for us.
Backtrace { backtrace_string: backtrace.to_string() }
});

if let Some(message) = host_state.take_panic_message() {
Error::AbortedDueToPanic(MessageWithBacktrace { message, backtrace })
} else {
Error::AbortedDueToTrap(MessageWithBacktrace {
message: trap.display_reason().to_string(),
backtrace: Some(backtrace),
})
let message = trap.root_cause().to_string();
Error::AbortedDueToTrap(MessageWithBacktrace { message, backtrace })
}
})
}
Expand All @@ -106,7 +96,7 @@ impl EntryPoint {
ctx: impl AsContext,
) -> std::result::Result<Self, &'static str> {
let entrypoint = func
.typed::<(u32, u32), u64, _>(ctx)
.typed::<(u32, u32), u64>(ctx)
.map_err(|_| "Invalid signature for direct entry point")?;
Ok(Self { call_type: EntryPointType::Direct { entrypoint } })
}
Expand All @@ -117,7 +107,7 @@ impl EntryPoint {
ctx: impl AsContext,
) -> std::result::Result<Self, &'static str> {
let dispatcher = dispatcher
.typed::<(u32, u32, u32), u64, _>(ctx)
.typed::<(u32, u32, u32), u64>(ctx)
.map_err(|_| "Invalid signature for wrapped entry point")?;
Ok(Self { call_type: EntryPointType::Wrapped { func, dispatcher } })
}
Expand Down
40 changes: 19 additions & 21 deletions client/executor/wasmtime/src/runtime.rs
Expand Up @@ -366,29 +366,27 @@ fn common_config(semantics: &Semantics) -> std::result::Result<wasmtime::Config,
MAX_WASM_PAGES
};

config.allocation_strategy(wasmtime::InstanceAllocationStrategy::Pooling {
strategy: wasmtime::PoolingAllocationStrategy::ReuseAffinity,

let mut pooling_config = wasmtime::PoolingAllocationConfig::default();
pooling_config
.strategy(wasmtime::PoolingAllocationStrategy::ReuseAffinity)
// Pooling needs a bunch of hard limits to be set; if we go over
// any of these then the instantiation will fail.
instance_limits: wasmtime::InstanceLimits {
// Current minimum values for kusama (as of 2022-04-14):
// size: 32384
// table_elements: 1249
// memory_pages: 2070
size: 128 * 1024,
table_elements: 8192,
memory_pages,

// We can only have a single of those.
tables: 1,
memories: 1,

// This determines how many instances of the module can be
// instantiated in parallel from the same `Module`.
count: 32,
},
});
//
// Current minimum values for kusama (as of 2022-04-14):
// size: 32384
// table_elements: 1249
// memory_pages: 2070
.instance_size(128 * 1024)
.instance_table_elements(8192)
.instance_memory_pages(memory_pages)
// We can only have a single of those.
.instance_tables(1)
.instance_memories(1)
// This determines how many instances of the module can be
// instantiated in parallel from the same `Module`.
.instance_count(32);

config.allocation_strategy(wasmtime::InstanceAllocationStrategy::Pooling(pooling_config));
}

Ok(config)
Expand Down
35 changes: 33 additions & 2 deletions client/executor/wasmtime/src/tests.rs
Expand Up @@ -226,8 +226,8 @@ fn deep_call_stack_wat(depth: usize) -> String {

// We need two limits here since depending on whether the code is compiled in debug
// or in release mode the maximum call depth is slightly different.
const CALL_DEPTH_LOWER_LIMIT: usize = 65478;
const CALL_DEPTH_UPPER_LIMIT: usize = 65514;
const CALL_DEPTH_LOWER_LIMIT: usize = 65455;
const CALL_DEPTH_UPPER_LIMIT: usize = 65503;

test_wasm_execution!(test_consume_under_1mb_of_stack_does_not_trap);
fn test_consume_under_1mb_of_stack_does_not_trap(instantiation_strategy: InstantiationStrategy) {
Expand Down Expand Up @@ -555,3 +555,34 @@ fn test_instances_without_reuse_are_not_leaked() {
instance.call_export("test_empty_return", &[0]).unwrap();
}
}

#[test]
fn test_rustix_version_matches_with_wasmtime() {
let metadata = cargo_metadata::MetadataCommand::new()
.manifest_path("../../../Cargo.toml")
.exec()
.unwrap();

let wasmtime_rustix = metadata
.packages
.iter()
.find(|pkg| pkg.name == "wasmtime-runtime")
.unwrap()
.dependencies
.iter()
.find(|dep| dep.name == "rustix")
.unwrap();
let our_rustix = metadata
.packages
.iter()
.find(|pkg| pkg.name == "sc-executor-wasmtime")
.unwrap()
.dependencies
.iter()
.find(|dep| dep.name == "rustix")
.unwrap();

if wasmtime_rustix.req != our_rustix.req {
panic!("our version of rustix ({0}) doesn't match wasmtime's ({1}); bump the version in `sc-executor-wasmtime`'s `Cargo.toml' to '{1}' and try again", our_rustix.req, wasmtime_rustix.req);
}
}
Expand Up @@ -371,14 +371,14 @@ fn generate_host_function_implementation(
registry.register_static(
#crate_::sp_wasm_interface::Function::name(&#struct_name),
|mut caller: #crate_::sp_wasm_interface::wasmtime::Caller<T::State>, #(#ffi_args_prototype),*|
-> std::result::Result<#ffi_return_ty, #crate_::sp_wasm_interface::wasmtime::Trap>
-> std::result::Result<#ffi_return_ty, #crate_::sp_wasm_interface::anyhow::Error>
{
T::with_function_context(caller, move |__function_context__| {
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
#struct_name::call(
__function_context__,
#(#ffi_names,)*
).map_err(#crate_::sp_wasm_interface::wasmtime::Trap::new)
).map_err(#crate_::sp_wasm_interface::anyhow::Error::msg)
}));
match result {
Ok(result) => result,
Expand All @@ -391,7 +391,7 @@ fn generate_host_function_implementation(
} else {
"host code panicked while being called by the runtime".to_owned()
};
return Err(#crate_::sp_wasm_interface::wasmtime::Trap::new(message));
return Err(#crate_::sp_wasm_interface::anyhow::Error::msg(message));
}
}
})
Expand Down
4 changes: 3 additions & 1 deletion primitives/wasm-interface/Cargo.toml
Expand Up @@ -18,9 +18,11 @@ codec = { package = "parity-scale-codec", version = "3.2.2", default-features =
impl-trait-for-tuples = "0.2.2"
log = { version = "0.4.17", optional = true }
wasmi = { version = "0.13", optional = true }
wasmtime = { version = "1.0.0", default-features = false, optional = true }
wasmtime = { version = "5.0.0", default-features = false, optional = true }
anyhow = { version = "1.0.68", optional = true }
sp-std = { version = "5.0.0", default-features = false, path = "../std" }

[features]
default = [ "std" ]
std = [ "codec/std", "log", "sp-std/std", "wasmi", "wasmtime" ]
wasmtime = [ "dep:wasmtime", "anyhow" ]
3 changes: 3 additions & 0 deletions primitives/wasm-interface/src/lib.rs
Expand Up @@ -41,6 +41,9 @@ macro_rules! if_wasmtime_is_enabled {
if_wasmtime_is_enabled! {
// Reexport wasmtime so that its types are accessible from the procedural macro.
pub use wasmtime;

// Wasmtime uses anyhow types but doesn't reexport them.
pub use anyhow;
}

/// Result type used by traits in this crate.
Expand Down
2 changes: 1 addition & 1 deletion utils/wasm-builder/Cargo.toml
Expand Up @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
ansi_term = "0.12.1"
build-helper = "0.1.1"
cargo_metadata = "0.14.2"
cargo_metadata = "0.15.2"
strum = { version = "0.24.1", features = ["derive"] }
tempfile = "3.1.0"
toml = "0.5.4"
Expand Down

0 comments on commit 47ecdb6

Please sign in to comment.