Skip to content

Commit

Permalink
feature(cargo-miden): support building Wasm component from a Cargo pr…
Browse files Browse the repository at this point in the history
…oject
  • Loading branch information
greenhat committed Sep 25, 2024
1 parent 8076326 commit a876d8b
Show file tree
Hide file tree
Showing 30 changed files with 1,198 additions and 1,111 deletions.
138 changes: 66 additions & 72 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ cargo-miden = { version = "0.0.7", path = "tools/cargo-miden" }
miden-integration-tests = { version = "0.0.0", path = "tests/integration" }
wat = "1.0.69"
blake3 = "1.5"
tokio = { version = "1.39.2", features = ["rt", "time", "macros"] }
tokio-util = "0.7.11"

[profile.dev]
lto = false
Expand Down
4 changes: 2 additions & 2 deletions midenc-debug/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ serde.workspace = true
ratatui = "0.28.0"
crossterm = { version = "0.28.1", features = ["event-stream"] }
tui-input = "0.10"
tokio = { version = "1.39.2", features = ["rt", "time", "macros"] }
tokio-util = "0.7.11"
tokio.workspace = true
tokio-util.workspace = true
futures = "0.3.30"
signal-hook = "0.3.17"
syntect = { version = "5.2.0", default-features = false, features = [
Expand Down
11 changes: 8 additions & 3 deletions sdk/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@ unsafe impl GlobalAlloc for BumpAlloc {
}

#[cfg(target_family = "wasm")]
#[link(wasm_import_module = "intrinsics::mem")]
extern "C" {
fn heap_base() -> *mut u8;
#[inline(never)]
#[no_mangle]
fn miden_intrinsics_mem_heap_base() -> *mut u8 {
unreachable!()
}
// #[link(wasm_import_module = "intrinsics::mem")]
// extern "C" {
// fn heap_base() -> *mut u8;
// }
8 changes: 4 additions & 4 deletions sdk/base-sys/src/bindings/tx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ pub fn create_note(
asset.inner[3],
tag,
note_type,
recipient.0[0],
recipient.0[1],
recipient.0[2],
recipient.0[3],
recipient.inner[0],
recipient.inner[1],
recipient.inner[2],
recipient.inner[3],
)
}
}
14 changes: 10 additions & 4 deletions sdk/base-sys/src/bindings/tx/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl From<AccountId> for Felt {

#[repr(transparent)]
pub struct CoreAsset {
pub(crate) inner: Word,
pub inner: Word,
}

impl CoreAsset {
Expand All @@ -26,13 +26,19 @@ impl CoreAsset {
}

#[repr(transparent)]
pub struct Recipient(pub(crate) Word);
pub struct Recipient {
pub inner: Word,
}

#[repr(transparent)]
pub struct Tag(pub(crate) Felt);
pub struct Tag {
pub inner: Felt,
}

#[repr(transparent)]
pub struct NoteId(pub(crate) Felt);

#[repr(transparent)]
pub struct NoteType(pub(crate) Felt);
pub struct NoteType {
pub inner: Felt,
}
22 changes: 16 additions & 6 deletions sdk/stdlib-sys/src/intrinsics/felt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ pub enum FeltError {
}

#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct Felt(f32);
#[derive(Copy, Clone, Debug)]
pub struct Felt {
pub inner: f32,
}

impl Felt {
/// Field modulus = 2^64 - 2^32 + 1
Expand Down Expand Up @@ -141,26 +143,34 @@ impl From<Felt> for u64 {

impl From<u32> for Felt {
fn from(value: u32) -> Self {
Self(unsafe { core::mem::transmute::<u32, f32>(value) })
Self {
inner: unsafe { core::mem::transmute::<u32, f32>(value) },
}
}
}

impl From<u16> for Felt {
fn from(value: u16) -> Self {
Self(unsafe { core::mem::transmute::<u32, f32>(value as u32) })
Self {
inner: unsafe { core::mem::transmute::<u32, f32>(value as u32) },
}
}
}

impl From<u8> for Felt {
fn from(value: u8) -> Self {
Self(unsafe { core::mem::transmute::<u32, f32>(value as u32) })
Self {
inner: unsafe { core::mem::transmute::<u32, f32>(value as u32) },
}
}
}

#[cfg(target_pointer_width = "32")]
impl From<usize> for Felt {
fn from(value: usize) -> Self {
Self(unsafe { core::mem::transmute(value as u32) })
Self {
inner: unsafe { core::mem::transmute(value as u32) },
}
}
}

Expand Down
51 changes: 33 additions & 18 deletions sdk/stdlib-sys/src/intrinsics/word.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,49 @@ use crate::Felt;

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C, align(32))]
pub struct Word([Felt; 4]);
impl Word {
pub const fn new(word: [Felt; 4]) -> Self {
Self(word)
}
}
impl From<[Felt; 4]> for Word {
fn from(word: [Felt; 4]) -> Self {
Self(word)
}
}
impl From<Word> for [Felt; 4] {
#[inline(always)]
fn from(word: Word) -> Self {
word.0
}
// pub struct Word([Felt; 4]);
pub struct Word {
pub inner: (Felt, Felt, Felt, Felt),
}
// impl Word {
// pub const fn new(word: [Felt; 4]) -> Self {
// Self { inner: word }
// }
// }
// impl From<[Felt; 4]> for Word {
// fn from(word: [Felt; 4]) -> Self {
// Self { inner: word }
// }
// }
// impl From<Word> for [Felt; 4] {
// #[inline(always)]
// fn from(word: Word) -> Self {
// word.inner
// }
// }
impl Index<usize> for Word {
type Output = Felt;

#[inline(always)]
fn index(&self, index: usize) -> &Self::Output {
self.0.index(index)
match index {
0 => &self.inner.0,
1 => &self.inner.1,
2 => &self.inner.2,
3 => &self.inner.3,
_ => unreachable!(),
}
}
}
impl IndexMut<usize> for Word {
#[inline(always)]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.0.index_mut(index)
match index {
0 => &mut self.inner.0,
1 => &mut self.inner.1,
2 => &mut self.inner.2,
3 => &mut self.inner.3,
_ => unreachable!(),
}
}
}
34 changes: 34 additions & 0 deletions tests/integration/src/compiler_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,15 @@ impl CompilerTestBuilder {

// Cargo-based source types share a lot of configuration in common
match self.source {
CompilerTestInputType::CargoMiden(ref config) => {
let manifest_path = project_dir.join("Cargo.toml");
command
.arg("--manifest-path")
.arg(manifest_path)
.arg("--release")
.arg("--target")
.arg(config.target.as_ref());
}
CompilerTestInputType::CargoComponent(_) => {
let manifest_path = project_dir.join("Cargo.toml");
command.arg("--manifest-path").arg(manifest_path).arg("--release");
Expand Down Expand Up @@ -635,6 +644,23 @@ impl CompilerTestBuilder {
builder
}

/// Compile the Rust project using cargo-miden
pub fn rust_source_cargo_miden(
cargo_project_folder: impl AsRef<Path>,
config: WasmTranslationConfig,
) -> Self {
let name = cargo_project_folder
.as_ref()
.file_stem()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or("".to_string());
let mut builder = CompilerTestBuilder::new(CompilerTestInputType::CargoMiden(
CargoTest::new(name, cargo_project_folder.as_ref().to_path_buf()),
));
builder.with_wasm_translation_config(config);
builder
}

/// Set the Rust source code to compile a library Cargo project to Wasm module
pub fn rust_source_cargo_lib(
cargo_project_folder: impl AsRef<Path>,
Expand Down Expand Up @@ -983,6 +1009,14 @@ impl CompilerTest {
CompilerTestBuilder::rust_source_cargo_component(cargo_project_folder, config).build()
}

/// Compile the Rust project using cargo-miden
pub fn rust_source_cargo_miden(
cargo_project_folder: impl AsRef<Path>,
config: WasmTranslationConfig,
) -> Self {
CompilerTestBuilder::rust_source_cargo_miden(cargo_project_folder, config).build()
}

/// Set the Rust source code to compile a library Cargo project to Wasm module
pub fn rust_source_cargo_lib(
cargo_project_folder: impl AsRef<Path>,
Expand Down
30 changes: 8 additions & 22 deletions tests/integration/src/rust_masm_tests/rust_sdk.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::path::PathBuf;

use expect_test::expect_file;
use midenc_frontend_wasm::WasmTranslationConfig;

use crate::{cargo_proj::project, compiler_test::sdk_crate_path, CompilerTest};

Expand All @@ -26,30 +27,15 @@ fn account() {
}

#[test]
fn basic_wallet() {
fn rust_sdk_basic_wallet() {
let _ = env_logger::builder().is_test(true).try_init();
let project_name = "rust_sdk_basic_wallet";
let source = r#"
pub struct Account;
impl Account {
#[no_mangle]
pub fn receive_asset(asset: CoreAsset) {
add_asset(asset);
}
#[no_mangle]
pub fn send_asset(asset: CoreAsset, tag: Tag, note_type: NoteType, recipient: Recipient) {
let asset = remove_asset(asset);
create_note(asset, tag, note_type, recipient);
}
}
"#;

let mut test = CompilerTest::rust_source_with_sdk(project_name, source, true, None, None);
let config = WasmTranslationConfig::default();
let mut test =
CompilerTest::rust_source_cargo_miden("../rust-apps-wasm/rust-sdk/basic-wallet", config);
let artifact_name = test.artifact_name();
test.expect_wasm(expect_file![format!("../../expected/{project_name}/{artifact_name}.wat")]);
test.expect_ir(expect_file![format!("../../expected/{project_name}/{artifact_name}.hir")]);
test.expect_wasm(expect_file![format!("../../expected/rust_sdk/{artifact_name}.wat")]);
test.expect_ir(expect_file![format!("../../expected/rust_sdk/{artifact_name}.hir")]);
// TODO: fix flaky test, "exec."_ZN19miden_sdk_tx_kernel9add_asset17h6f4cff304c095ffc" is
// changing the suffix on every n-th run test.expect_masm(expect_file![format!("../../
// expected/{project_name}/{artifact_name}.masm" )]);
Expand Down
1 change: 1 addition & 0 deletions tests/rust-apps-wasm/rust-sdk/basic-wallet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
41 changes: 41 additions & 0 deletions tests/rust-apps-wasm/rust-sdk/basic-wallet/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 43 additions & 0 deletions tests/rust-apps-wasm/rust-sdk/basic-wallet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[package]
name = "basic_wallet"
version = "0.1.0"
edition = "2021"

[lib]
# Build this crate as a self-contained, C-style dynamic library
# This is required to emit the proper Wasm module type
crate-type = ["cdylib"]

[dependencies]
# Miden SDK consists of a stdlib (intrinsic functions for VM ops, stdlib functions and types)
# and transaction kernel API for the Miden rollup
miden-sdk = { path = "../../../../sdk/sdk" }
wit-bindgen-rt = "0.28"


[profile.release]
# optimize the output for size
opt-level = "z"
# Explicitly disable panic infrastructure on Wasm, as
# there is no proper support for them anyway, and it
# ensures that panics do not pull in a bunch of standard
# library code unintentionally
panic = "abort"

[profile.dev]
# Explicitly disable panic infrastructure on Wasm, as
# there is no proper support for them anyway, and it
# ensures that panics do not pull in a bunch of standard
# library code unintentionally
panic = "abort"
opt-level = 1
debug-assertions = false
overflow-checks = false
debug = true

# TODO: switch to miden table
[package.metadata.component]
package = "miden:basic-wallet"

[package.metadata.component.target.dependencies]
"miden:base" = { path = "wit-sdk" }
Loading

0 comments on commit a876d8b

Please sign in to comment.