Skip to content

Commit

Permalink
Revert "Revert "Update to wasmi v0.32 and add lazy validation (#1488)…
Browse files Browse the repository at this point in the history
…"" (#1577)

* Revert "Revert "Update to wasmi v0.32 and add lazy validation (#1488)" (#1527)"

This reverts commit 961c920.

* Update wasmi

* Fix compilation

* Update CHANGELOG

* Update wasmi

* Cargo.lock changes didn't commit

* Another update
  • Loading branch information
tomaka authored Jan 16, 2024
1 parent bbec949 commit cf264c1
Show file tree
Hide file tree
Showing 17 changed files with 110 additions and 28 deletions.
28 changes: 24 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions full-node/src/consensus_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ impl ConsensusService {
executor::host::HostVmPrototype::new(executor::host::Config {
module: finalized_code,
heap_pages,
exec_hint: executor::vm::ExecHint::CompileAheadOfTime, // TODO: probably should be decided by the optimisticsync
exec_hint: executor::vm::ExecHint::ValidateAndCompile, // TODO: probably should be decided by the optimisticsync
allow_unresolved_imports: false,
})
.map_err(InitError::FinalizedRuntimeInit)?
Expand Down Expand Up @@ -2570,7 +2570,7 @@ impl SyncBackground {
}
all::ProcessOne::WarpSyncBuildRuntime(build_runtime) => {
let (new_sync, outcome) =
build_runtime.build(all::ExecHint::CompileAheadOfTime, true);
build_runtime.build(all::ExecHint::ValidateAndCompile, true);
self.sync = new_sync;
if let Err(err) = outcome {
self.log_callback.log(
Expand Down Expand Up @@ -3165,7 +3165,7 @@ pub async fn execute_block_and_insert(
let vm = host::HostVmPrototype::new(host::Config {
module: &new_code,
heap_pages: new_heap_pages,
exec_hint: executor::vm::ExecHint::CompileAheadOfTime,
exec_hint: executor::vm::ExecHint::ValidateAndCompile,
allow_unresolved_imports: false,
})
.map_err(ExecuteBlockInvalidBlockError::InvalidNewRuntime)?;
Expand Down
2 changes: 1 addition & 1 deletion full-node/src/json_rpc_service/runtime_caches_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl RuntimeCachesService {
executor::host::Config {
module: &code,
heap_pages,
exec_hint: executor::vm::ExecHint::CompileAheadOfTime,
exec_hint: executor::vm::ExecHint::ValidateAndCompile,
allow_unresolved_imports: true, // TODO: configurable? or if not, document
},
)
Expand Down
2 changes: 1 addition & 1 deletion full-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ async fn open_database(
genesis_storage.value(b":heappages"),
)
.unwrap(),
exec_hint: executor::vm::ExecHint::Oneshot,
exec_hint: executor::vm::ExecHint::ValidateAndExecuteOnce,
allow_unresolved_imports: true,
})
.unwrap()
Expand Down
4 changes: 3 additions & 1 deletion fuzz/fuzz_targets/wasm-module-wasmi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ libfuzzer_sys::fuzz_target!(|data: &[u8]| {
let _ = smoldot::executor::host::HostVmPrototype::new(smoldot::executor::host::Config {
module: data,
heap_pages: smoldot::executor::DEFAULT_HEAP_PAGES,
exec_hint: smoldot::executor::vm::ExecHint::ForceWasmi,
exec_hint: smoldot::executor::vm::ExecHint::ForceWasmi {
lazy_validation: false,
},
allow_unresolved_imports: true,
});
});
2 changes: 1 addition & 1 deletion lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ siphasher = { version = "1.0.0", default-features = false }
slab = { version = "0.4.8", default-features = false }
smallvec = { version = "1.12.0", default-features = false }
twox-hash = { version = "1.6.3", default-features = false }
wasmi = { version = "0.31.0", default-features = false }
wasmi = { version = "0.32.0-beta.5", default-features = false }
x25519-dalek = { version = "2.0.0-rc.3", default-features = false, features = ["alloc", "precomputed-tables", "static_secrets", "zeroize"] }
zeroize = { version = "1.6.0", default-features = false, features = ["alloc"] }

Expand Down
2 changes: 1 addition & 1 deletion lib/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl ChainSpec {
let vm_prototype = executor::host::HostVmPrototype::new(executor::host::Config {
module: &wasm_code,
heap_pages,
exec_hint: executor::vm::ExecHint::Oneshot,
exec_hint: executor::vm::ExecHint::ValidateAndExecuteOnce,
allow_unresolved_imports: true,
})
.map_err(FromGenesisStorageError::VmInitialization)?;
Expand Down
3 changes: 2 additions & 1 deletion lib/src/database/full_sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ impl SqliteFullDatabase {
let Ok(runtime) = host::HostVmPrototype::new(host::Config {
module: code,
heap_pages,
exec_hint: executor::vm::ExecHint::Oneshot,
exec_hint:
executor::vm::ExecHint::ExecuteOnceWithNonDeterministicValidation,
allow_unresolved_imports: true,
}) else {
todo!()
Expand Down
2 changes: 1 addition & 1 deletion lib/src/executor/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
//! let prototype = HostVmPrototype::new(Config {
//! module: &wasm_binary_code,
//! heap_pages: HeapPages::from(2048),
//! exec_hint: smoldot::executor::vm::ExecHint::Oneshot,
//! exec_hint: smoldot::executor::vm::ExecHint::ValidateAndExecuteOnce,
//! allow_unresolved_imports: false
//! }).unwrap();
//! prototype.run_no_param("Core_version").unwrap().into()
Expand Down
2 changes: 1 addition & 1 deletion lib/src/executor/runtime_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1792,7 +1792,7 @@ impl Inner {
let vm_prototype = match host::HostVmPrototype::new(host::Config {
module: req.wasm_code(),
heap_pages: executor::DEFAULT_HEAP_PAGES,
exec_hint: vm::ExecHint::Oneshot,
exec_hint: vm::ExecHint::ValidateAndExecuteOnce,
allow_unresolved_imports: false, // TODO: what is a correct value here?
}) {
Ok(w) => w,
Expand Down
2 changes: 1 addition & 1 deletion lib/src/executor/runtime_call/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn execute_blocks() {
host::HostVmPrototype::new(host::Config {
module: code,
heap_pages,
exec_hint: crate::executor::vm::ExecHint::Oneshot,
exec_hint: crate::executor::vm::ExecHint::ExecuteOnceWithNonDeterministicValidation,
allow_unresolved_imports: false,
})
.unwrap()
Expand Down
66 changes: 58 additions & 8 deletions lib/src/executor/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl VirtualMachinePrototype {
),
feature = "wasmtime"
))]
ExecHint::CompileAheadOfTime => VirtualMachinePrototypeInner::Jit(
ExecHint::ValidateAndCompile => VirtualMachinePrototypeInner::Jit(
jit::JitPrototype::new(config.module_bytes, config.symbols)?,
),
#[cfg(not(all(
Expand All @@ -175,13 +175,41 @@ impl VirtualMachinePrototype {
),
feature = "wasmtime"
)))]
ExecHint::CompileAheadOfTime => VirtualMachinePrototypeInner::Interpreter(
interpreter::InterpreterPrototype::new(config.module_bytes, config.symbols)?,
ExecHint::ValidateAndCompile => VirtualMachinePrototypeInner::Interpreter(
interpreter::InterpreterPrototype::new(
config.module_bytes,
interpreter::CompilationMode::Eager,
config.symbols,
)?,
),
ExecHint::Oneshot | ExecHint::Untrusted | ExecHint::ForceWasmi => {
ExecHint::ValidateAndExecuteOnce | ExecHint::Untrusted => {
VirtualMachinePrototypeInner::Interpreter(
interpreter::InterpreterPrototype::new(
config.module_bytes,
interpreter::CompilationMode::Eager,
config.symbols,
)?,
)
}
ExecHint::CompileWithNonDeterministicValidation
| ExecHint::ExecuteOnceWithNonDeterministicValidation => {
VirtualMachinePrototypeInner::Interpreter(
interpreter::InterpreterPrototype::new(
config.module_bytes,
interpreter::CompilationMode::Lazy,
config.symbols,
)?,
)
}
ExecHint::ForceWasmi { lazy_validation } => {
VirtualMachinePrototypeInner::Interpreter(
interpreter::InterpreterPrototype::new(
config.module_bytes,
if lazy_validation {
interpreter::CompilationMode::Lazy
} else {
interpreter::CompilationMode::Eager
},
config.symbols,
)?,
)
Expand Down Expand Up @@ -829,18 +857,37 @@ impl fmt::Debug for VirtualMachine {
pub enum ExecHint {
/// The WebAssembly code will be instantiated once and run many times.
/// If possible, compile this WebAssembly code ahead of time.
CompileAheadOfTime,
ValidateAndCompile,

/// The WebAssembly code will be instantiated once and run many times.
/// Contrary to [`ExecHint::ValidateAndCompile`], the WebAssembly code isn't fully validated
/// ahead of time, meaning that invalid WebAssembly modules might successfully be compiled,
/// which is an indesirable property in some contexts.
CompileWithNonDeterministicValidation,

/// The WebAssembly code is expected to be only run once.
///
/// > **Note**: This isn't a hard requirement but a hint.
Oneshot,
ValidateAndExecuteOnce,

/// The WebAssembly code will be instantiated once and run many times.
/// Contrary to [`ExecHint::ValidateAndExecuteOnce`], the WebAssembly code isn't fully
/// validated ahead of time, meaning that invalid WebAssembly modules might successfully be
/// compiled, which is an indesirable property in some contexts.
ExecuteOnceWithNonDeterministicValidation,

/// The WebAssembly code running through this VM is untrusted.
Untrusted,

/// Forces using the `wasmi` backend.
///
/// This variant is useful for testing purposes.
ForceWasmi,
ForceWasmi {
/// If `true`, lazy validation is enabled. This leads to a faster initialization time,
/// but can also successfully validate invalid modules, which is an indesirable property
/// in some contexts.
lazy_validation: bool,
},
/// Forces using the `wasmtime` backend.
///
/// This variant is useful for testing purposes.
Expand Down Expand Up @@ -885,7 +932,10 @@ impl ExecHint {
///
/// > **Note**: This function is most useful for testing purposes.
pub fn available_engines() -> impl Iterator<Item = ExecHint> {
iter::once(ExecHint::ForceWasmi).chain(Self::force_wasmtime_if_available())
iter::once(ExecHint::ForceWasmi {
lazy_validation: false,
})
.chain(Self::force_wasmtime_if_available())
}

/// Returns `ForceWasmtime` if it is available on the current platform, and `None` otherwise.
Expand Down
6 changes: 5 additions & 1 deletion lib/src/executor/vm/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use super::{
use alloc::{borrow::ToOwned as _, string::ToString as _, sync::Arc, vec::Vec};
use core::fmt;

pub use wasmi::CompilationMode;

/// See [`super::VirtualMachinePrototype`].
pub struct InterpreterPrototype {
/// Base components that can be used to recreate a prototype later if desired.
Expand Down Expand Up @@ -52,6 +54,7 @@ impl InterpreterPrototype {
/// See [`super::VirtualMachinePrototype::new`].
pub fn new(
module_bytes: &[u8],
compilation_mode: CompilationMode,
symbols: &mut dyn FnMut(&str, &str, &Signature) -> Result<usize, ()>,
) -> Result<Self, NewErr> {
let engine = {
Expand All @@ -66,6 +69,7 @@ impl InterpreterPrototype {
config.wasm_mutable_global(false);
config.wasm_saturating_float_to_int(false);
config.wasm_tail_call(false);
config.compilation_mode(compilation_mode);

wasmi::Engine::new(&config)
};
Expand Down Expand Up @@ -129,7 +133,7 @@ impl InterpreterPrototype {
&mut store,
func_type.clone(),
move |_caller, parameters, _ret| {
Err(wasmi::core::Trap::from(InterruptedTrap {
Err(wasmi::Error::host(InterruptedTrap {
function_index,
parameters: parameters
.iter()
Expand Down
2 changes: 1 addition & 1 deletion lib/src/transactions/validate/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn validate_from_proof() {
module: hex::decode(&test.runtime_code).unwrap(),
heap_pages: executor::DEFAULT_HEAP_PAGES,
allow_unresolved_imports: true,
exec_hint: executor::vm::ExecHint::Oneshot,
exec_hint: executor::vm::ExecHint::ExecuteOnceWithNonDeterministicValidation,
})
.unwrap();

Expand Down
2 changes: 1 addition & 1 deletion light-base/src/runtime_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2862,7 +2862,7 @@ async fn compile_runtime<TPlat: PlatformRef>(
let module = code.as_ref().ok_or(RuntimeError::CodeNotFound)?;
let heap_pages = executor::storage_heap_pages_to_value(heap_pages.as_deref())
.map_err(RuntimeError::InvalidHeapPages)?;
let exec_hint = executor::vm::ExecHint::CompileAheadOfTime;
let exec_hint = executor::vm::ExecHint::CompileWithNonDeterministicValidation;

// We try once with `allow_unresolved_imports: false`. If this fails due to unresolved
// import, we try again but with `allowed_unresolved_imports: true`.
Expand Down
6 changes: 5 additions & 1 deletion light-base/src/sync_service/standalone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,11 @@ impl<TPlat: PlatformRef> Task<TPlat> {
// Warp syncing compiles the runtime. The compiled runtime will later be yielded
// in the `WarpSyncFinished` variant, which is then provided as an event.
let before_instant = self.platform.now();
let (new_sync, error) = req.build(all::ExecHint::CompileAheadOfTime, true);
// Because the runtime being compiled has been validated by 2/3rds of the
// validators of the chain, we can assume that it is valid. Doing so significantly
// increases the compilation speed.
let (new_sync, error) =
req.build(all::ExecHint::CompileWithNonDeterministicValidation, true);
let elapsed = self.platform.now() - before_instant;
match error {
Ok(()) => {
Expand Down
1 change: 1 addition & 0 deletions wasm-node/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Changed

- The WebAssembly runtime is now compiled lazily, meaning that only the code that is executed is validated and translated. Thanks to this, compiling a runtime is now four times faster and the time to head of the chain is around 200ms faster. ([#1488](https://github.com/smol-dot/smoldot/pull/1488), [#1577](https://github.com/smol-dot/smoldot/pull/1577))
- Most of the log messages emitted by smoldot have been modified in order to unify their syntax and be easier to parse programatically. ([#1560](https://github.com/smol-dot/smoldot/pull/1560))
- Added support for the `ext_panic_handler_abort_on_panic_version_1` host function. ([#1573](https://github.com/smol-dot/smoldot/pull/1573))

Expand Down

0 comments on commit cf264c1

Please sign in to comment.