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