From 88ac7bc66a808e7ae20599bdb99ed2780a096b28 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:21:50 -0800 Subject: [PATCH] Add wasi p2 example using rustc native p2 target Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com> --- .gitignore | 5 +- Cargo.lock | 45 ++- Justfile | 12 +- src/hyperlight_wasm/Cargo.toml | 6 + .../examples/monte_carlo_example/main.rs | 105 ++++++ src/wasip2_guest/Cargo.lock | 325 ++++++++++++++++++ src/wasip2_guest/Cargo.toml | 31 ++ src/wasip2_guest/src/lib.rs | 57 +++ src/wasip2_guest/wit/monte-carlo.wit | 15 + 9 files changed, 592 insertions(+), 9 deletions(-) create mode 100644 src/hyperlight_wasm/examples/monte_carlo_example/main.rs create mode 100644 src/wasip2_guest/Cargo.lock create mode 100644 src/wasip2_guest/Cargo.toml create mode 100644 src/wasip2_guest/src/lib.rs create mode 100644 src/wasip2_guest/wit/monte-carlo.wit diff --git a/.gitignore b/.gitignore index b99517dc..2fe108e9 100644 --- a/.gitignore +++ b/.gitignore @@ -478,5 +478,8 @@ target/ # MSVC Windows builds of rustc generate these, which store debugging information *.pdb -src/component_sample/**/*.wasm + +# WebAssembly build artifacts +*.wasm + src/wasmsamples/components/bindings/ diff --git a/Cargo.lock b/Cargo.lock index 3633d9dc..c1bbbe32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1483,7 +1483,7 @@ dependencies = [ "mshv-ioctls", "opentelemetry", "page_size", - "rand", + "rand 0.9.2", "rust-embed", "serde_json", "sha256", @@ -1531,6 +1531,7 @@ dependencies = [ "opentelemetry-semantic-conventions", "opentelemetry_sdk", "page_size", + "rand 0.8.5", "tar", "tokio", "toml", @@ -1999,7 +2000,7 @@ dependencies = [ "ordered-float 5.1.0", "quanta", "radix_trie", - "rand", + "rand 0.9.2", "rand_xoshiro", "sketches-ddsketch", ] @@ -2225,7 +2226,7 @@ dependencies = [ "futures-util", "opentelemetry", "percent-encoding", - "rand", + "rand 0.9.2", "thiserror 2.0.17", "tokio", "tokio-stream", @@ -2531,14 +2532,35 @@ dependencies = [ "nibble_vec", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", ] [[package]] @@ -2548,7 +2570,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", ] [[package]] @@ -2566,7 +2597,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" dependencies = [ - "rand_core", + "rand_core 0.9.3", ] [[package]] diff --git a/Justfile b/Justfile index 4ad33011..d0823a84 100644 --- a/Justfile +++ b/Justfile @@ -5,6 +5,7 @@ mkdir-arg := if os() == "windows" { "-Force" } else { "-p" } latest-release:= if os() == "windows" {"$(git tag -l --sort=v:refname | select -last 2 | select -first 1)"} else {`git tag -l --sort=v:refname | tail -n 2 | head -n 1`} wit-world := if os() == "windows" { "$env:WIT_WORLD=\"" + justfile_directory() + "\\src\\component_sample\\wit\\component-world.wasm" + "\";" } else { "WIT_WORLD=" + justfile_directory() + "/src/component_sample/wit/component-world.wasm" } wit-world-c := if os() == "windows" { "$env:WIT_WORLD=\"" + justfile_directory() + "\\src\\wasmsamples\\components\\runcomponent-world.wasm" + "\";" } else { "WIT_WORLD=" + justfile_directory() + "/src/wasmsamples/components/runcomponent-world.wasm" } +wit-world-monte-carlo := if os() == "windows" { "$env:WIT_WORLD=\"" + justfile_directory() + "\\src\\wasip2_guest\\monte-carlo-world.wasm" + "\";" } else { "WIT_WORLD=" + justfile_directory() + "/src/wasip2_guest/monte-carlo-world.wasm" } set windows-shell := ["pwsh.exe", "-NoLogo", "-Command"] @@ -32,6 +33,7 @@ mkdir-redist target=default-target: compile-wit: wasm-tools component wit ./src/wasmsamples/components/runcomponent.wit -w -o ./src/wasmsamples/components/runcomponent-world.wasm wasm-tools component wit ./src/component_sample/wit/example.wit -w -o ./src/component_sample/wit/component-world.wasm + wasm-tools component wit ./src/wasip2_guest/wit/monte-carlo.wit -w -o ./src/wasip2_guest/monte-carlo-world.wasm build-examples target=default-target features="": (build-wasm-examples target features) (build-rust-wasm-examples target features) (build-rust-component-examples target features) @@ -50,6 +52,13 @@ build-rust-component-examples target=default-target features="": (compile-wit) cd ./src/component_sample && cargo component build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }} cargo run {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--features " + features } }} -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} --component ./src/component_sample/target/wasm32-unknown-unknown/{{ target }}/component_sample.wasm ./x64/{{ target }}/component_sample.aot +build-monte-carlo-example features="": (compile-wit) (mkdir-redist "release") + # Monte Carlo Pi example using native wasm32-wasip2 + wit-bindgen + # Always build in release mode to avoid WASI dependencies (debug mode pulls in entire WASI for some reason) + rustup target add wasm32-wasip2 + cd ./src/wasip2_guest && cargo build --lib --target wasm32-wasip2 --release + cargo run {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--features " + features } }} -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} --component ./src/wasip2_guest/target/wasm32-wasip2/release/monte_carlo.wasm ./x64/release/monte_carlo.aot + check target=default-target: cargo check --profile={{ if target == "debug" {"dev"} else { target } }} cd src/rust_wasm_samples && cargo check --profile={{ if target == "debug" {"dev"} else { target } }} @@ -99,9 +108,10 @@ examples-ci target=default-target features="": (build-rust-wasm-examples target) cargo run {{ if features =="" {''} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics cargo run {{ if features =="" {"--no-default-features --features kvm,mshv3"} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics -examples-components target=default-target features="": (build-rust-component-examples target) +examples-components target=default-target features="": (build-rust-component-examples target) (build-monte-carlo-example) {{ wit-world }} cargo run {{ if features =="" {''} else {"--no-default-features -F kvm -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example component_example {{ wit-world-c }} cargo run {{ if features =="" {''} else {"--no-default-features -F kvm -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example c-component + {{ wit-world-monte-carlo }} cargo run {{ if features =="" {''} else {"--no-default-features -F kvm -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example monte_carlo_example # warning, compares to and then OVERWRITES the given baseline bench-ci baseline target="release" features="": diff --git a/src/hyperlight_wasm/Cargo.toml b/src/hyperlight_wasm/Cargo.toml index f674521b..53c12bfe 100644 --- a/src/hyperlight_wasm/Cargo.toml +++ b/src/hyperlight_wasm/Cargo.toml @@ -59,6 +59,11 @@ name = "interruption" path = "examples/interruption/main.rs" test = true +[[example]] +name = "monte_carlo_example" +path = "examples/monte_carlo_example/main.rs" +test = true + [dependencies] hyperlight-host = { workspace = true } libc = { version = "0.2.180" } @@ -92,6 +97,7 @@ tracing = "0.1.44" tracing-subscriber = {version = "0.3.22", features = ["std", "env-filter"]} tracing-opentelemetry = "0.32.1" uuid = { version = "1.19.0", features = ["v4"] } +rand = "0.8" [build-dependencies] cfg_aliases = "0.2.1" diff --git a/src/hyperlight_wasm/examples/monte_carlo_example/main.rs b/src/hyperlight_wasm/examples/monte_carlo_example/main.rs new file mode 100644 index 00000000..eb66b6d7 --- /dev/null +++ b/src/hyperlight_wasm/examples/monte_carlo_example/main.rs @@ -0,0 +1,105 @@ +/* +Copyright 2024 The Hyperlight Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +//! Monte Carlo Pi Estimator - Host Example +//! +//! Demonstrates running a WASI P2 component built with native `wasm32-wasip2` +//! target and `wit-bindgen`. The host provides a random number generator +//! that the guest component imports to estimate Pi. +//! +//! Build the guest first: `just build-monte-carlo-example` +//! Run: `just examples-components` + +extern crate alloc; + +use std::env; +use std::path::Path; + +use rand::rngs::StdRng; +use rand::{Rng, SeedableRng}; + +mod bindings { + hyperlight_component_macro::host_bindgen!("../wasip2_guest/monte-carlo-world.wasm"); +} + +/// Host-provided RNG state for the guest component. +/// +/// The guest cannot generate randomness in `no_std` mode, so the host +/// provides random numbers via the imported `random` interface. +struct State { + rng: StdRng, +} + +impl State { + fn new() -> Self { + State { + rng: StdRng::from_entropy(), + } + } +} + +impl bindings::my::monte_carlo::Random for State { + fn random(&mut self) -> f32 { + self.rng.r#gen::() + } +} + +#[allow(refining_impl_trait)] +impl bindings::my::monte_carlo::EstimatorImports for State { + type Random = State; + + fn random(&mut self) -> &mut Self::Random { + self + } +} + +fn main() { + let state = State::new(); + + let mut sb: hyperlight_wasm::ProtoWasmSandbox = hyperlight_wasm::SandboxBuilder::new() + .with_guest_input_buffer_size(1000000) + .with_guest_heap_size(10000000) + .with_guest_stack_size(1000000) + .build() + .unwrap(); + + let rt = bindings::register_host_functions(&mut sb, state); + + let sb = sb.load_runtime().unwrap(); + + // Always look in x64/release since the guest is always built in release mode + // (debug mode pulls in WASI dependencies that we don't support) + let proj_dir = env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); + let mod_path = Path::new(&proj_dir) + .join("../../x64/release/monte_carlo.aot") + .canonicalize() + .expect("Failed to find monte_carlo.aot - run 'just build-monte-carlo-example' first"); + let sb = sb.load_module(mod_path).unwrap(); + + let mut wrapped = bindings::EstimatorSandbox { sb, rt }; + + // Estimate pi with different sample sizes + for samples in [100, 1000, 10000] { + let pi_estimate = + bindings::my::monte_carlo::EstimatorExports::estimate_pi(&mut wrapped, samples); + println!( + "Pi estimate with {} samples: {:.6} (error: {:.6})", + samples, + pi_estimate, + (pi_estimate - std::f32::consts::PI).abs() + ); + } +} diff --git a/src/wasip2_guest/Cargo.lock b/src/wasip2_guest/Cargo.lock new file mode 100644 index 00000000..f7ecdc88 --- /dev/null +++ b/src/wasip2_guest/Cargo.lock @@ -0,0 +1,325 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "syn" +version = "2.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "wasip2-guest" +version = "0.1.0" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "bitflags", + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "zmij" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65" diff --git a/src/wasip2_guest/Cargo.toml b/src/wasip2_guest/Cargo.toml new file mode 100644 index 00000000..def8e3bb --- /dev/null +++ b/src/wasip2_guest/Cargo.toml @@ -0,0 +1,31 @@ +# WASI P2 Guest Component Example +# +# This crate demonstrates building a WebAssembly component using the NATIVE +# Rust `wasm32-wasip2` target with `wit-bindgen`, rather than `cargo-component`. +# +# Key differences from cargo-component approach: +# - Uses `wasm32-wasip2` target directly (rustup target add wasm32-wasip2) +# - Uses `wit-bindgen` crate for guest bindings (not cargo-component) +# - Requires `#![no_std]` and `#![no_main]` for minimal output +# - MUST build in release mode (debug pulls in WASI dependencies) +# +# Build command: +# cargo build --lib --target wasm32-wasip2 --release +# +# The generated .wasm is a valid WASI P2 component that can be compiled +# to AOT format using hyperlight-wasm-aot. + +[package] +name = "wasip2-guest" +version = "0.1.0" +edition = "2024" + +[lib] +name = "monte_carlo" +path = "src/lib.rs" +crate-type = ["cdylib"] + +[workspace] # standalone crate, not part of parent workspace + +[dependencies] +wit-bindgen = "0.51.0" diff --git a/src/wasip2_guest/src/lib.rs b/src/wasip2_guest/src/lib.rs new file mode 100644 index 00000000..d27ead80 --- /dev/null +++ b/src/wasip2_guest/src/lib.rs @@ -0,0 +1,57 @@ +/* +Copyright 2024 The Hyperlight Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +//! Monte Carlo Pi Estimator - WASI P2 Component Example +//! +//! This guest component demonstrates host-guest interaction where the guest +//! depends on the host to provide random numbers (since `no_std` components +//! cannot generate randomness). +//! +//! Build with: `cargo build --lib --target wasm32-wasip2 --release` +//! +//! Note: Must use release mode - debug mode pulls in WASI dependencies. + +#![no_std] +#![no_main] + +wit_bindgen::generate!({ + world: "estimator", + path: "wit", +}); + +struct Component; + +impl Guest for Component { + fn estimate_pi(samples: u32) -> f32 { + let mut inside_circle = 0u32; + + for _ in 0..samples { + // Get random x and y from host (we can't generate randomness!) + let x = my::monte_carlo::random::random(); + let y = my::monte_carlo::random::random(); + + // Check if point is inside unit circle + if x * x + y * y <= 1.0 { + inside_circle += 1; + } + } + + // Pi ≈ 4 * (points inside circle / total points) + 4.0 * (inside_circle as f32) / (samples as f32) + } +} + +export!(Component); diff --git a/src/wasip2_guest/wit/monte-carlo.wit b/src/wasip2_guest/wit/monte-carlo.wit new file mode 100644 index 00000000..f2c9be9f --- /dev/null +++ b/src/wasip2_guest/wit/monte-carlo.wit @@ -0,0 +1,15 @@ +package my:monte-carlo; + +/// Host provides random numbers (guest can't generate them) +interface random { + /// Returns a random f32 in the range [0.0, 1.0) + random: func() -> f32; +} + +world estimator { + import random; + + /// Estimate pi using n random samples + /// Returns the estimate of pi + export estimate-pi: func(samples: u32) -> f32; +}