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

Commit

Permalink
Integrate Wasmtime for runtime execution (#3869)
Browse files Browse the repository at this point in the history
* executor: Use non wasmi-specific execution in tests.

* executor: Move all runtime execution tests into tests file.

* executor: Use test_case macro to easily execute tests with different
Wasm execution methods.

* executor: Convert errors to strings with Display, not Debug.

* node-executor: Rewrite benchmarks with criterion.

They were not passing compilation before and criterion seems to be more
widely used in Substrate.

* executor: Begin implementation of Wasm runtime.

The implementation demonstrates the outline of the execution, but does
not link against the external host functions.

* executor: Define and implement basic FunctionExecutor.

The SandboxCapabilities::invoke is still left unimplemented.

* executor: Implement host function trampoline generation.

* executor: Instantiate and link runtime module to env module.

* executor: Provide input data during wasmtime execution.

* executor: Implement SandboxCapabilites::invoke for wasmtime executor.

* executor: Integrate and test wasmtime execution method.

* executor: Improve FunctionExecution error messages.

* Scope the unsafe blocks to be smaller.

* Rename TrampolineState to EnvState.

* Let EnvState own its own compiler instead of unsafe lifetime cast.

* Refactor out some common wasmi/wasmtime logic.

* Typos and cosmetic changes.

* More trampoline comments.

* Cargo.lock update.

* cli: CLI option for running Substrate with compiled Wasm execution.

* executor: Switch dependency from fork to official wasmtime repo.

* Quiet down cranelift logs.

* Explicitly catch panics during host calls.

We do this to ensure that panics do not cross language boundaries.

* Additional checks and clarifications in make_trampoline.

* Fixes after merge from master and panic safety for wasmtime
instantiation.
  • Loading branch information
jimpo authored Nov 1, 2019
1 parent f237d8c commit c297536
Show file tree
Hide file tree
Showing 25 changed files with 2,862 additions and 652 deletions.
466 changes: 466 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,4 @@ members = [
[profile.release]
# Substrate runtime requires unwinding.
panic = "unwind"

5 changes: 5 additions & 0 deletions core/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,8 @@ rpassword = "4.0.1"

[dev-dependencies]
tempdir = "0.3.7"

[features]
wasmtime = [
"service/wasmtime",
]
1 change: 1 addition & 0 deletions core/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,7 @@ fn init_logger(pattern: &str) {
// Disable info logging by default for some modules:
builder.filter(Some("ws"), log::LevelFilter::Off);
builder.filter(Some("hyper"), log::LevelFilter::Warn);
builder.filter(Some("cranelift_wasm"), log::LevelFilter::Warn);
// Enable info for others.
builder.filter(None, log::LevelFilter::Info);

Expand Down
21 changes: 20 additions & 1 deletion core/cli/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,32 @@ arg_enum! {
pub enum WasmExecutionMethod {
// Uses an interpreter.
Interpreted,
// Uses a compiled runtime.
Compiled,
}
}

impl WasmExecutionMethod {
/// Returns list of variants that are not disabled by feature flags.
fn enabled_variants() -> Vec<&'static str> {
Self::variants()
.iter()
.cloned()
.filter(|&name| cfg!(feature = "wasmtime") || name != "Compiled")
.collect()
}
}

impl Into<service::config::WasmExecutionMethod> for WasmExecutionMethod {
fn into(self) -> service::config::WasmExecutionMethod {
match self {
WasmExecutionMethod::Interpreted => service::config::WasmExecutionMethod::Interpreted,
#[cfg(feature = "wasmtime")]
WasmExecutionMethod::Compiled => service::config::WasmExecutionMethod::Compiled,
#[cfg(not(feature = "wasmtime"))]
WasmExecutionMethod::Compiled => panic!(
"Substrate must be compiled with \"wasmtime\" feature for compiled Wasm execution"
),
}
}
}
Expand Down Expand Up @@ -429,7 +448,7 @@ pub struct RunCmd {
#[structopt(
long = "wasm-execution",
value_name = "METHOD",
possible_values = &WasmExecutionMethod::variants(),
possible_values = &WasmExecutionMethod::enabled_variants(),
case_insensitive = true,
default_value = "Interpreted"
)]
Expand Down
20 changes: 20 additions & 0 deletions core/executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ log = "0.4.8"
libsecp256k1 = "0.3.0"
tiny-keccak = "1.5.0"

cranelift-codegen = { version = "0.46.1", optional = true }
cranelift-entity = { version = "0.46.1", optional = true }
cranelift-frontend = { version = "0.46.1", optional = true }
cranelift-native = { version = "0.46.1", optional = true }
cranelift-wasm = { version = "0.46.1", optional = true }
wasmtime-environ = { version = "0.2", optional = true, git = "https://github.com/CraneStation/wasmtime.git", rev = "71dd73d6" }
wasmtime-jit = { version = "0.2", optional = true, git = "https://github.com/CraneStation/wasmtime.git", rev = "71dd73d6" }
wasmtime-runtime = { version = "0.2", optional = true, git = "https://github.com/CraneStation/wasmtime.git", rev = "71dd73d6" }

[dev-dependencies]
assert_matches = "1.3.0"
wabt = "0.9.2"
Expand All @@ -31,7 +40,18 @@ runtime-test = { package = "substrate-runtime-test", path = "runtime-test" }
substrate-client = { path = "../client" }
substrate-offchain = { path = "../offchain/" }
state_machine = { package = "substrate-state-machine", path = "../state-machine" }
test-case = "0.3.3"

[features]
default = []
wasm-extern-trace = []
wasmtime = [
"cranelift-codegen",
"cranelift-entity",
"cranelift-frontend",
"cranelift-native",
"cranelift-wasm",
"wasmtime-environ",
"wasmtime-jit",
"wasmtime-runtime",
]
23 changes: 19 additions & 4 deletions core/executor/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

use serializer;
use wasmi;
#[cfg(feature = "wasmtime")]
use wasmtime_jit::{ActionError, SetupError};

/// Result type alias.
pub type Result<T> = std::result::Result<T, Error>;
Expand All @@ -31,6 +33,9 @@ pub enum Error {
Trap(wasmi::Trap),
/// Wasmi loading/instantiating error
Wasmi(wasmi::Error),
/// Wasmtime action error
#[cfg(feature = "wasmtime")]
Wasmtime(ActionError),
/// Error in the API. Parameter is an error message.
ApiError(String),
/// Method is not found
Expand Down Expand Up @@ -75,9 +80,9 @@ pub enum Error {
/// Someone tried to allocate more memory than the allowed maximum per allocation.
#[display(fmt="Requested allocation size is too large")]
RequestedAllocationTooLarge,
/// Executing the given function failed with the given error.
#[display(fmt="Function execution failed with: {}", _0)]
FunctionExecution(String),
/// Execution of a host function failed.
#[display(fmt="Host function {} execution failed with: {}", _0, _1)]
FunctionExecution(String, String),
}

impl std::error::Error for Error {
Expand Down Expand Up @@ -116,6 +121,16 @@ pub enum WasmError {
InvalidModule,
/// Wasm code could not be deserialized.
CantDeserializeWasm,
/// The module does not export a linear memory named `memory`.
InvalidMemory,
/// The number of heap pages requested is disallowed by the module.
InvalidHeapPages,
/// Instantiation error.
Instantiation(Error),
Instantiation(String),
/// The compiler does not support the host machine as a target.
#[cfg(feature = "wasmtime")]
MissingCompilerSupport(&'static str),
/// Wasmtime setup error.
#[cfg(feature = "wasmtime")]
WasmtimeSetup(SetupError),
}
Loading

0 comments on commit c297536

Please sign in to comment.