From ae56c4a31a223fd607569c8ff6b560c46d6a969f Mon Sep 17 00:00:00 2001 From: Marcin S Date: Sun, 21 May 2023 12:26:54 -0400 Subject: [PATCH 1/3] Executor: Add `create_runtime_from_artifact_bytes` Also export `WasmtimeRuntime`, returned by the `create_runtime*` functions. --- client/executor/wasmtime/src/lib.rs | 5 ++- client/executor/wasmtime/src/runtime.rs | 49 ++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/client/executor/wasmtime/src/lib.rs b/client/executor/wasmtime/src/lib.rs index c45478ec46a37..82e62b4a5dd3c 100644 --- a/client/executor/wasmtime/src/lib.rs +++ b/client/executor/wasmtime/src/lib.rs @@ -37,6 +37,7 @@ mod util; mod tests; pub use runtime::{ - create_runtime, create_runtime_from_artifact, prepare_runtime_artifact, Config, - DeterministicStackLimit, InstantiationStrategy, Semantics, + create_runtime, create_runtime_from_artifact, create_runtime_from_artifact_bytes, + prepare_runtime_artifact, Config, DeterministicStackLimit, InstantiationStrategy, Semantics, + WasmtimeRuntime, }; diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index c9a2c83e0493c..67ea0bf239cf2 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -537,7 +537,7 @@ enum CodeSupplyMode<'a> { /// The runtime is instantiated using the given runtime blob. Fresh(RuntimeBlob), - /// The runtime is instantiated using a precompiled module. + /// The runtime is instantiated using a precompiled module at the given path. /// /// This assumes that the code is already prepared for execution and the same `Config` was /// used. @@ -545,6 +545,12 @@ enum CodeSupplyMode<'a> { /// We use a `Path` here instead of simply passing a byte slice to allow `wasmtime` to /// map the runtime's linear memory on supported platforms in a copy-on-write fashion. Precompiled(&'a Path), + + /// The runtime is instantiated using a precompiled module with the given bytes. + /// + /// This assumes that the code is already prepared for execution and the same `Config` was + /// used. + PrecompiledBytes(&'a [u8]), } /// Create a new `WasmtimeRuntime` given the code. This function performs translation from Wasm to @@ -589,6 +595,31 @@ where do_create_runtime::(CodeSupplyMode::Precompiled(compiled_artifact_path), config) } +/// The same as [`create_runtime`] but takes the bytes of a precompiled artifact, +/// which makes this function considerably faster than [`create_runtime`], +/// but slower than the more optimized [`create_runtime_from_artifact`]. +/// Useful in very niche cases. +/// +/// # Safety +/// +/// The caller must ensure that the compiled artifact passed here was: +/// 1) produced by [`prepare_runtime_artifact`], +/// 2) was not modified, +/// +/// Failure to adhere to these requirements might lead to crashes and arbitrary code execution. +/// +/// It is ok though if the compiled artifact was created by code of another version or with +/// different configuration flags. In such case the caller will receive an `Err` deterministically. +pub unsafe fn create_runtime_from_artifact_bytes( + compiled_artifact_bytes: &[u8], + config: Config, +) -> std::result::Result +where + H: HostFunctions, +{ + do_create_runtime::(CodeSupplyMode::PrecompiledBytes(compiled_artifact_bytes), config) +} + /// # Safety /// /// This is only unsafe if called with [`CodeSupplyMode::Artifact`]. See @@ -663,6 +694,22 @@ where (module, InternalInstantiationStrategy::Builtin) }, + CodeSupplyMode::PrecompiledBytes(compiled_artifact_bytes) => { + if let InstantiationStrategy::LegacyInstanceReuse = + config.semantics.instantiation_strategy + { + return Err(WasmError::Other("the legacy instance reuse instantiation strategy is incompatible with precompiled modules".into())); + } + + // SAFETY: The unsafety of `deserialize` is covered by this function. The + // responsibilities to maintain the invariants are passed to the caller. + // + // See [`create_runtime_from_artifact_bytes`] for more details. + let module = wasmtime::Module::deserialize(&engine, compiled_artifact_bytes) + .map_err(|e| WasmError::Other(format!("cannot deserialize module: {:#}", e)))?; + + (module, InternalInstantiationStrategy::Builtin) + }, }; let mut linker = wasmtime::Linker::new(&engine); From 5d75b5b400b60c2e3e226d9c3e501c0f03f2bd09 Mon Sep 17 00:00:00 2001 From: Marcin S Date: Mon, 22 May 2023 08:16:06 -0400 Subject: [PATCH 2/3] Update doc and add missing benchmark --- client/executor/benches/bench.rs | 9 ++++++++- client/executor/wasmtime/src/runtime.rs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/client/executor/benches/bench.rs b/client/executor/benches/bench.rs index 772898b8c76b3..2844b510edc74 100644 --- a/client/executor/benches/bench.rs +++ b/client/executor/benches/bench.rs @@ -188,12 +188,19 @@ fn bench_call_instance(c: &mut Criterion) { }, ), ( - "pooling_vanilla", + "pooling_vanilla_fresh", Method::Compiled { instantiation_strategy: InstantiationStrategy::Pooling, precompile: false, }, ), + ( + "pooling_vanilla_precompiled", + Method::Compiled { + instantiation_strategy: InstantiationStrategy::Pooling, + precompile: true, + }, + ), ( "pooling_cow_fresh", Method::Compiled { diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 67ea0bf239cf2..66e0f98abe354 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -435,7 +435,7 @@ pub struct DeterministicStackLimit { /// All of the CoW strategies (with `CopyOnWrite` suffix) are only supported when either: /// a) we're running on Linux, /// b) we're running on an Unix-like system and we're precompiling -/// our module beforehand. +/// our module beforehand and instantiating from a file. /// /// If the CoW variant of a strategy is unsupported the executor will /// fall back to the non-CoW equivalent. From 80f39b04092e008a539a4567a7301cb51aa08b89 Mon Sep 17 00:00:00 2001 From: Marcin S Date: Mon, 22 May 2023 10:41:17 -0400 Subject: [PATCH 3/3] Update doc --- client/executor/wasmtime/src/runtime.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/executor/wasmtime/src/runtime.rs b/client/executor/wasmtime/src/runtime.rs index 66e0f98abe354..23b069870aa36 100644 --- a/client/executor/wasmtime/src/runtime.rs +++ b/client/executor/wasmtime/src/runtime.rs @@ -598,7 +598,7 @@ where /// The same as [`create_runtime`] but takes the bytes of a precompiled artifact, /// which makes this function considerably faster than [`create_runtime`], /// but slower than the more optimized [`create_runtime_from_artifact`]. -/// Useful in very niche cases. +/// This is especially slow on non-Linux Unix systems. Useful in very niche cases. /// /// # Safety ///