near / nearcore

Reference client for NEAR Protocol
https://near.org
GNU General Public License v3.0
2.33k stars 629 forks source link

Error happened while deserializing the module (stop using parity_wasm) #8358

Open petersalomonsen opened 1 year ago

petersalomonsen commented 1 year ago

Describe the bug

When calling any contract deployed with emscripten or optimized by binaryen after the WebAssembly sign-ext features where introduced you'll get the error "Error happened while deserializing the module"

This is because nearvm use of parity_wasm parser which does not recognize the sign-ext WebAssembly opcodes.

To Reproduce Deploy a contract with wasm opcode 192 (0xC0) i32.extend8_s

Expected behavior nearvm should not fail to deserialize the module

Screenshots

image

Version (please complete the following information):

Additional context To mitigate the problem for now it's possible to use wasm-opt (from binaryen) on the WebAssembly binary file with the --signext-lowering option.

See how it was mitigated in my use case here:

image

https://github.com/petersalomonsen/quickjs-rust-near/pull/11/commits/8168133a752d64b74d69cb9e5b0e794f6a2b50df

nagisa commented 1 year ago

Currently we only support the wasm-core-1 specification and nothing more. This is true across the runtime stack and isn’t a limitation imposed by just pwasm_utils/parity_wasm alone.

I would expect the compilers to provide the options on which extensions are usable by the target. Rust/LLVM, for example, allow toggling many of them pretty much arbitrarily (exceptions are things like the threads proposal which affects how the standard library is compiled and requires a new target). As far as Emscripten is concerned, there appears to be a -msimd128 to enable the SIMD proposal and I would imagine -mno-simd128 to disable it. I would be surprised if there isn’t something similar for signext proposal too.

The finite-wasm work that we’re looking to land this upcoming quarter (so~on) will replace pwasm-utils code and does have the code to support many more webassembly extensions, but we'll still need to implement the proposals throughout the rest of the pipeline. Doing so may require NEPs for each extension and thus the process may end up taking a significant amount of time while those processes conclude.

petersalomonsen commented 1 year ago

thanks! I noticed that both wasmparser and parity_wasm is used for deserializing the contract and without checking further thought that parity_wasm (which seems to be archived) was something left from earlier days. But if it is as you say that the wasm runtime used does not support these instructions then I understand it's a bit more work involved.

For the sign-ext opcodes, it seems quite easy to mitigate using wasm-opt with the --signext-lowering option.

MantisClone commented 1 year ago

I searched for ways to disable the sign-ext opcodes on the compiler and ran across this issue that seems to indicate that the option to disable sign-ext exists :+1: but that it's not working. :cry: https://github.com/rust-lang/rust/issues/109807

Thus, I will likely pursue the wasm-opt --signext-lowering approach.