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

Commit c297536

Browse files
authored
Integrate Wasmtime for runtime execution (#3869)
* 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.
1 parent f237d8c commit c297536

25 files changed

+2862
-652
lines changed

Cargo.lock

Lines changed: 466 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,4 @@ members = [
108108
[profile.release]
109109
# Substrate runtime requires unwinding.
110110
panic = "unwind"
111+

core/cli/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,8 @@ rpassword = "4.0.1"
3838

3939
[dev-dependencies]
4040
tempdir = "0.3.7"
41+
42+
[features]
43+
wasmtime = [
44+
"service/wasmtime",
45+
]

core/cli/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,7 @@ fn init_logger(pattern: &str) {
897897
// Disable info logging by default for some modules:
898898
builder.filter(Some("ws"), log::LevelFilter::Off);
899899
builder.filter(Some("hyper"), log::LevelFilter::Warn);
900+
builder.filter(Some("cranelift_wasm"), log::LevelFilter::Warn);
900901
// Enable info for others.
901902
builder.filter(None, log::LevelFilter::Info);
902903

core/cli/src/params.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,32 @@ arg_enum! {
5050
pub enum WasmExecutionMethod {
5151
// Uses an interpreter.
5252
Interpreted,
53+
// Uses a compiled runtime.
54+
Compiled,
55+
}
56+
}
57+
58+
impl WasmExecutionMethod {
59+
/// Returns list of variants that are not disabled by feature flags.
60+
fn enabled_variants() -> Vec<&'static str> {
61+
Self::variants()
62+
.iter()
63+
.cloned()
64+
.filter(|&name| cfg!(feature = "wasmtime") || name != "Compiled")
65+
.collect()
5366
}
5467
}
5568

5669
impl Into<service::config::WasmExecutionMethod> for WasmExecutionMethod {
5770
fn into(self) -> service::config::WasmExecutionMethod {
5871
match self {
5972
WasmExecutionMethod::Interpreted => service::config::WasmExecutionMethod::Interpreted,
73+
#[cfg(feature = "wasmtime")]
74+
WasmExecutionMethod::Compiled => service::config::WasmExecutionMethod::Compiled,
75+
#[cfg(not(feature = "wasmtime"))]
76+
WasmExecutionMethod::Compiled => panic!(
77+
"Substrate must be compiled with \"wasmtime\" feature for compiled Wasm execution"
78+
),
6079
}
6180
}
6281
}
@@ -429,7 +448,7 @@ pub struct RunCmd {
429448
#[structopt(
430449
long = "wasm-execution",
431450
value_name = "METHOD",
432-
possible_values = &WasmExecutionMethod::variants(),
451+
possible_values = &WasmExecutionMethod::enabled_variants(),
433452
case_insensitive = true,
434453
default_value = "Interpreted"
435454
)]

core/executor/Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ log = "0.4.8"
2323
libsecp256k1 = "0.3.0"
2424
tiny-keccak = "1.5.0"
2525

26+
cranelift-codegen = { version = "0.46.1", optional = true }
27+
cranelift-entity = { version = "0.46.1", optional = true }
28+
cranelift-frontend = { version = "0.46.1", optional = true }
29+
cranelift-native = { version = "0.46.1", optional = true }
30+
cranelift-wasm = { version = "0.46.1", optional = true }
31+
wasmtime-environ = { version = "0.2", optional = true, git = "https://github.com/CraneStation/wasmtime.git", rev = "71dd73d6" }
32+
wasmtime-jit = { version = "0.2", optional = true, git = "https://github.com/CraneStation/wasmtime.git", rev = "71dd73d6" }
33+
wasmtime-runtime = { version = "0.2", optional = true, git = "https://github.com/CraneStation/wasmtime.git", rev = "71dd73d6" }
34+
2635
[dev-dependencies]
2736
assert_matches = "1.3.0"
2837
wabt = "0.9.2"
@@ -31,7 +40,18 @@ runtime-test = { package = "substrate-runtime-test", path = "runtime-test" }
3140
substrate-client = { path = "../client" }
3241
substrate-offchain = { path = "../offchain/" }
3342
state_machine = { package = "substrate-state-machine", path = "../state-machine" }
43+
test-case = "0.3.3"
3444

3545
[features]
3646
default = []
3747
wasm-extern-trace = []
48+
wasmtime = [
49+
"cranelift-codegen",
50+
"cranelift-entity",
51+
"cranelift-frontend",
52+
"cranelift-native",
53+
"cranelift-wasm",
54+
"wasmtime-environ",
55+
"wasmtime-jit",
56+
"wasmtime-runtime",
57+
]

core/executor/src/error.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
1919
use serializer;
2020
use wasmi;
21+
#[cfg(feature = "wasmtime")]
22+
use wasmtime_jit::{ActionError, SetupError};
2123

2224
/// Result type alias.
2325
pub type Result<T> = std::result::Result<T, Error>;
@@ -31,6 +33,9 @@ pub enum Error {
3133
Trap(wasmi::Trap),
3234
/// Wasmi loading/instantiating error
3335
Wasmi(wasmi::Error),
36+
/// Wasmtime action error
37+
#[cfg(feature = "wasmtime")]
38+
Wasmtime(ActionError),
3439
/// Error in the API. Parameter is an error message.
3540
ApiError(String),
3641
/// Method is not found
@@ -75,9 +80,9 @@ pub enum Error {
7580
/// Someone tried to allocate more memory than the allowed maximum per allocation.
7681
#[display(fmt="Requested allocation size is too large")]
7782
RequestedAllocationTooLarge,
78-
/// Executing the given function failed with the given error.
79-
#[display(fmt="Function execution failed with: {}", _0)]
80-
FunctionExecution(String),
83+
/// Execution of a host function failed.
84+
#[display(fmt="Host function {} execution failed with: {}", _0, _1)]
85+
FunctionExecution(String, String),
8186
}
8287

8388
impl std::error::Error for Error {
@@ -116,6 +121,16 @@ pub enum WasmError {
116121
InvalidModule,
117122
/// Wasm code could not be deserialized.
118123
CantDeserializeWasm,
124+
/// The module does not export a linear memory named `memory`.
125+
InvalidMemory,
126+
/// The number of heap pages requested is disallowed by the module.
127+
InvalidHeapPages,
119128
/// Instantiation error.
120-
Instantiation(Error),
129+
Instantiation(String),
130+
/// The compiler does not support the host machine as a target.
131+
#[cfg(feature = "wasmtime")]
132+
MissingCompilerSupport(&'static str),
133+
/// Wasmtime setup error.
134+
#[cfg(feature = "wasmtime")]
135+
WasmtimeSetup(SetupError),
121136
}

0 commit comments

Comments
 (0)