154988febSNick Fitzgerald# Deterministic Wasm Execution
254988febSNick Fitzgerald
354988febSNick FitzgeraldThe WebAssembly language is *mostly* deterministic, but there are a few places
454988febSNick Fitzgeraldwhere non-determinism slips in. This page documents how to use Wasmtime to
554988febSNick Fitzgeraldexecute Wasm programs fully deterministically, even when the Wasm language spec
654988febSNick Fitzgeraldallows for non-determinism.
754988febSNick Fitzgerald
854988febSNick Fitzgerald## Make Sure All Imports are Deterministic
954988febSNick Fitzgerald
1054988febSNick FitzgeraldDo not give Wasm programs access to non-deterministic host functions.
1154988febSNick Fitzgerald
1254988febSNick FitzgeraldWhen using WASI, use
1354988febSNick Fitzgerald[`wasi-virt`](https://github.com/bytecodealliance/WASI-Virt) to virtualize
1454988febSNick Fitzgeraldnon-deterministic APIs like clocks and file systems.
1554988febSNick Fitzgerald
1654988febSNick Fitzgerald## Enable IEEE-754 `NaN` canonicalization
1754988febSNick Fitzgerald
1854988febSNick FitzgeraldSome Wasm opcodes can result in `NaN` (not-a-number) values. The IEEE-754 spec
1954988febSNick Fitzgeralddefines a whole range of `NaN` values and the Wasm spec does not require that
2054988febSNick FitzgeraldWasm always generates any particular `NaN` value, it could be any one of
2154988febSNick Fitzgeraldthem. This non-determinism can then be observed by the Wasm program by storing
2254988febSNick Fitzgeraldthe `NaN` value to memory or bitcasting it to an integer. Therefore, Wasmtime
2354988febSNick Fitzgeraldcan be configured to canonicalize all `NaN`s into a particular, canonical `NaN`
2454988febSNick Fitzgeraldvalue. The downside is that this adds overhead to Wasm's floating-point
2554988febSNick Fitzgeraldinstructions.
2654988febSNick Fitzgerald
2754988febSNick FitzgeraldSee
2854988febSNick Fitzgerald[wasmtime::Config::cranelift_nan_canonicalization](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.cranelift_nan_canonicalization)
2954988febSNick Fitzgeraldfor more details.
3054988febSNick Fitzgerald
3154988febSNick Fitzgerald## Make the Relaxed SIMD Proposal Deterministic
3254988febSNick Fitzgerald
3354988febSNick FitzgeraldThe relaxed SIMD proposal gives Wasm programs access to SIMD operations that
3454988febSNick Fitzgeraldcannot be made to execute both identically and performantly across different
35*af40b578SBlock Piratearchitectures. The proposal gave up determinism across different architectures in
3654988febSNick Fitzgeraldorder to maintain portable performance.
3754988febSNick Fitzgerald
3854988febSNick FitzgeraldAt the cost of worse runtime performance, Wasmtime can deterministically execute
3954988febSNick Fitzgeraldthis proposal's instructions. See
4054988febSNick Fitzgerald[wasmtime::Config::relaxed_simd_deterministic](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.relaxed_simd_deterministic)
4154988febSNick Fitzgeraldfor more details.
4254988febSNick Fitzgerald
4354988febSNick FitzgeraldAlternatively, you can simply disable the proposal completely. See
4454988febSNick Fitzgerald[`wasmtime::Config::wasm_relaxed_simd`](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.wasm_relaxed_simd)
4554988febSNick Fitzgeraldfor more details.
4654988febSNick Fitzgerald
4754988febSNick Fitzgerald## Handling Non-Deterministic Memory and Table Growth
4854988febSNick Fitzgerald
4954988febSNick FitzgeraldAll WebAssembly memories and tables have an associated minimum, or initial, size
5054988febSNick Fitzgeraldand an optional maximum size. When the maximum size is not present, that means
5154988febSNick Fitzgerald"unlimited". If a memory or table is already at its maximum size, then attempts
5254988febSNick Fitzgeraldto grow them will always fail. If they are below their maximum size, however,
5354988febSNick Fitzgeraldthen the `memory.grow` and `table.grow` instructions are allowed to
5454988febSNick Fitzgeraldnon-deterministicaly succeed or fail (for example, when the host system does not
5554988febSNick Fitzgeraldhave enough memory available to satisfy that growth).
5654988febSNick Fitzgerald
5754988febSNick FitzgeraldYou can make this deterministic in a variety of ways:
5854988febSNick Fitzgerald
5954988febSNick Fitzgerald* Disallow Wasm programs that use memories and tables via a
6054988febSNick Fitzgerald  [limiter](https://docs.rs/wasmtime/latest/wasmtime/struct.Store.html#method.limiter)
6154988febSNick Fitzgerald  that rejects non-zero-sized memories and tables.
6254988febSNick Fitzgerald
6354988febSNick Fitzgerald* Use a [custom memory
6454988febSNick Fitzgerald  creator](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.with_host_memory)
6554988febSNick Fitzgerald  that allocates the maximum size up front so that growth will either always
6654988febSNick Fitzgerald  succeed or fail before the program has begun execution.
6754988febSNick Fitzgerald
6854988febSNick Fitzgerald* Use [the `wasmparser` crate](https://crates.io/crates/wasmparser) to write a
6954988febSNick Fitzgerald  little validator program that rejects Wasm modules that use
7054988febSNick Fitzgerald  `{memory,table}.grow` instructions or alternatively rejects memories and
7154988febSNick Fitzgerald  tables that do not have a maximum size equal to their minimum size (which,
7254988febSNick Fitzgerald  again, means that their allocation must happen completely up front, and if
7354988febSNick Fitzgerald  allocation fails, it will have failed before the Wasm program began
7454988febSNick Fitzgerald  executing).
7554988febSNick Fitzgerald
7654988febSNick Fitzgerald## Use Deterministic Interruption, If Any
7754988febSNick Fitzgerald
7854988febSNick FitzgeraldIf you are making Wasm execution interruptible, use [deterministic fuel-based
79fd788dc9SGarmashAlexinterruption](./examples-interrupting-wasm.md#deterministic-fuel) rather than
8054988febSNick Fitzgeraldnon-deterministic epoch-based interruption.
81