jedisct1 / rust-minisign

A pure Rust implementation of the Minisign signature tool.
Other
90 stars 15 forks source link

Does not run on wasmer due to getrandom feature #27

Closed ThetaSinner closed 5 months ago

ThetaSinner commented 6 months ago

I ran into errors running this in WASM on wasmer. The problem is something I've run into a few times which is that getrandom with the js feature enabled does not work. I need to enable custom which I can do but there is no way for me to disable the js feature that this crate enables.

I am opening an issue rather than a PR because I can't find a tidy way to fix this.

I changed the Cargo.toml from

[target.'cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown"))'.dependencies]
getrandom = { version = "0.2", optional = false, default-features = false, features = ["js"] }

[target.'cfg(not(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown")))'.dependencies]
getrandom = { version = "0.2", optional = false, default-features = false }

[dependencies]
scrypt = { version = "0.11.0", default-features = false }

to

[dependencies]
scrypt = { version = "0.11.0", default-features = false }
getrandom = { version = "0.2", default-features = false }

[target.'cfg(any(windows, unix))'.dependencies]
rpassword = "7.3.1"

[features]
wasm_js = ["getrandom/js"]
wasm_custom = ["getrandom/custom"]

Which I think will work for everyone, but it also means that everyone targeting WASM has to explicitly opt-in to a feature. I'm okay with that for myself and this solves my problem. Any objections to this suggestion?

jedisct1 commented 6 months ago

The current state of Rust and WebAssembly is a shit show.

How are you compiling it?

I tried compiling rsign2 for wasix.

cargo wasix is currently broken:

$ rustc --version
rustc 1.76.0 (07dca489a 2024-02-04)

$  cargo wasix run
You might have to run `cargo update` to ensure the dependencies are used properly
error: package `clap v4.5.1` cannot be built because it requires rustc 1.74 or newer, while the currently active rustc version is 1.73.0-dev
Either upgrade to rustc 1.74 or newer, or use
cargo update clap@4.5.1 --precise ver
where `ver` is the latest version of `clap` supporting rustc 1.73.0-dev

But cargo wasi works:

$ cargo wasi build
$ wasmer target/wasm32-wasi/debug/rsign.wasm
Usage: rsign2 [COMMAND]
ThetaSinner commented 6 months ago

Thanks for getting back to me! That's fair to say :)

I'm just compiling my project with cargo build --release --target wasm32-unknown-unknown. That part works fine. It's when I deploy my code into wasmer and it gets put through the wasmer-cranelift-compiler that I get an error

error occurred during test run: internal_error: Wasm runtime error: RuntimeError: WasmError { error: Compile("Error while importing \"__wbindgen_placeholder__\".\"__wbindgen_is_object\": unknown import. Expected Function(FunctionType { params: [I32], results: [I32] })") }

I don't know a huge amount about this step but I can find out more if that would be useful. My understanding stops with, the wasm I build for wasmer shouldn't contain anything that it that is intended for a different/JavaScript runtime.

jedisct1 commented 6 months ago

There are different variants of WebAssembly.

wasm32-unknown-unknown is a funny name for what's called wasm32-freestanding elsewhere. That variant doesn't include any functions to get random numbers. It's generally only used to generate code that runs in web browsers, and calls JavaScript functions in order to do so.

Unlike a runtime like bun or node, wasmer doesn't support JavaScript. But the variants it supports are called emscripten, wasi-core and wasix.

Rust is not able to target emscripten any more until someone steps up to work on it, and the tool to target Wasix seems currently broken. So, we're left with wasi-core, which is also planned to be abandoned for yet another variant, even though it may live on under a different name and with different maintainers, but for now, that works.

Long story short, you need to use the wasm32-wasi target instead of wasm32-unknown-unknown.

ThetaSinner commented 5 months ago

Sorry it took me a while to get around to trying this. If I build the wasm with wasm32-wasi I get a different error

error: Compile(\"Error while importing \\\"wasi_snapshot_preview1\\\".\\\"fd_write\\\": unknown import. Expected Function(FunctionType { params: [I32, I32, I32, I32], results: [I32] })\") }), wasm_trace: [] }))

This wasmer instance has been sandboxed so it can't access anything on the host. It's providing the random implementation that's missing in wasm32-unknown-unknown apparently.

Thanks for the suggestions anyway! I've figured out that I can depend on minisign-verify instead which means moving things around a bit but builds beautifully into wasm for this environment :)