Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
80031ce
add support for wasm with cairo 1
FrancoGiachetta Sep 30, 2025
056e966
correct Cargo.lock
FrancoGiachetta Sep 30, 2025
5540f96
fix workflow
FrancoGiachetta Oct 1, 2025
45eaa2a
fix workflow
FrancoGiachetta Oct 1, 2025
ebc6cab
add std feature for cairo1-run
FrancoGiachetta Oct 1, 2025
43a3c72
use a different program as an example
FrancoGiachetta Oct 1, 2025
709abe8
fmt + fix workflow
FrancoGiachetta Oct 1, 2025
02d1fea
update changelog
FrancoGiachetta Oct 1, 2025
1972c3e
use default features for cairo 1
FrancoGiachetta Oct 1, 2025
6d048d9
try fix ci
FrancoGiachetta Oct 1, 2025
d9a1438
compile example
FrancoGiachetta Oct 1, 2025
00c29f3
use cairo 1 compiler
FrancoGiachetta Oct 1, 2025
1d0fc9b
try to fix ci
FrancoGiachetta Oct 1, 2025
0356219
correct compiler command
FrancoGiachetta Oct 1, 2025
597ebac
fetch program from cache
FrancoGiachetta Oct 1, 2025
c7bb8c8
try fix ci
FrancoGiachetta Oct 1, 2025
31f833c
save in cache
FrancoGiachetta Oct 1, 2025
0e09763
add sierra path to CAIRO_PROGRAMS_PATH
FrancoGiachetta Oct 1, 2025
2af23d2
try fix
FrancoGiachetta Oct 1, 2025
32a2f6c
change hashFiles function
FrancoGiachetta Oct 2, 2025
b0cafef
make cairo1-run cli require std feature
FrancoGiachetta Oct 2, 2025
64604a6
remove unnecessary file path in hashFiles function
FrancoGiachetta Oct 2, 2025
4ae89c8
format toml
FrancoGiachetta Oct 2, 2025
0d40642
improve readme + remove todo
FrancoGiachetta Oct 2, 2025
186a862
update makefile so that make tests does not complain
FrancoGiachetta Oct 3, 2025
51df761
Merge branch 'main' into support-wasm-with-cairo1
FrancoGiachetta Oct 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ env:
cairo_programs/**/*.json
!cairo_programs/manually_compiled/*
examples/wasm-demo/src/array_sum.json
cairo_programs/cairo-1-programs/bitwise.sierra
TEST_COLLECT_COVERAGE: 1
PROPTEST_CASES: 100

Expand Down Expand Up @@ -48,6 +49,7 @@ jobs:
- cairo_test_programs
- cairo_1_test_contracts
- cairo_2_test_contracts
- wasm_cairo_1_example
name: Build Cairo programs
runs-on: ubuntu-24.04
steps:
Expand Down Expand Up @@ -90,15 +92,19 @@ jobs:
echo PATH=$PATH >> $GITHUB_ENV

- name: Install cairo 1 compiler
if: steps.cache-programs.outputs.cache-hit != 'true' && matrix.program-target == 'cairo_1_test_contracts'
if: steps.cache-programs.outputs.cache-hit != 'true' && (matrix.program-target == 'cairo_1_test_contracts' || matrix.program-target == 'wasm_cairo_1_example')
run: make build-cairo-1-compiler

- name: Install cairo 2 compiler
if: steps.cache-programs.outputs.cache-hit != 'true' && matrix.program-target == 'cairo_2_test_contracts'
run: make build-cairo-2-compiler

- name: Build Cairo 1 WASM example
if: steps.cache-programs.outputs.cache-hit != 'true' && matrix.program-target == 'wasm_cairo_1_example'
run: ./cairo1/bin/cairo-compile -r cairo_programs/cairo-1-programs/bitwise.cairo cairo_programs/cairo-1-programs/bitwise.sierra

- name: Build programs
if: steps.cache-programs.outputs.cache-hit != 'true'
if: steps.cache-programs.outputs.cache-hit != 'true' && matrix.program-target != 'wasm_cairo_1_example'
run: make -j ${{ matrix.program-target }}

# NOTE: used to reduce the amount of cache steps we need in later jobs
Expand Down Expand Up @@ -146,6 +152,12 @@ jobs:
path: ${{ env.CAIRO_PROGRAMS_PATH }}
key: cairo_2_test_contracts-cache-${{ hashFiles('cairo_programs/**/*.cairo', 'examples/wasm-demo/src/array_sum.cairo', 'Makefile', 'requirements.txt') }}
fail-on-cache-miss: true
- name: Fetch WASM Cairo 1 Example
uses: actions/cache/restore@v3
with:
path: ${{ env.CAIRO_PROGRAMS_PATH }}
key: wasm_cairo_1_example-cache-${{ hashFiles('cairo_programs/**/*.cairo', 'examples/wasm-demo/src/array_sum.cairo', 'Makefile', 'requirements.txt') }}
fail-on-cache-miss: true

- name: Merge caches
uses: actions/cache/save@v3
Expand Down Expand Up @@ -819,6 +831,27 @@ jobs:
cd examples/wasm-demo
wasm-pack build --target=web

wasm-demo-cairo1:
name: Build the wasm demo cairo1
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Install wasm-pack dep
run: npm install -g wasm-pack

- name: Make deps
run: make deps

- name: Build wasm-demo-cairo1
run: |
./cairo1/bin/cairo-compile -r cairo_programs/cairo-1-programs/bitwise.cairo cairo_programs/cairo-1-programs/bitwise.sierra
cd examples/wasm-demo-cairo1
wasm-pack build --target=web

compare-factorial-outputs-all-layouts:
name: Compare factorial outputs for all layouts
needs: [ build-programs, build-release ]
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#### Upcoming Changes

* feat: Add support for WASM with Cairo 1 [#2216](https://github.com/lambdaclass/cairo-vm/pull/2216)

* fix: Added `cairo_1_test_contracts` and `cairo_2_test_contracts` as dependencies for `test-extensive_hints` target [#2201](https://github.com/lambdaclass/cairo-vm/pull/2201)

* breaking: Store constants in Hint Data [#2191](https://github.com/lambdaclass/cairo-vm/pull/2191)
Expand Down
13 changes: 13 additions & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"vm",
"hint_accountant",
"examples/wasm-demo",
"examples/wasm-demo-cairo1",
"cairo1-run",
"cairo-vm-tracer",
"examples/hyper_threading",
Expand Down Expand Up @@ -89,6 +90,9 @@ lto = "fat"
# Tell `rustc` to optimize for small code size.
opt-level = "s"

[profile.release.package.wasm-demo-cairo1]
opt-level = "s"

[profile.test.package.proptest]
opt-level = 3

Expand Down
10 changes: 9 additions & 1 deletion cairo1-run/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ keywords.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cairo-vm = { workspace = true, features = ["std", "cairo-1-hints", "clap"] }
cairo-vm = { workspace = true, features = ["cairo-1-hints", "clap"] }
serde_json = { workspace = true }

cairo-lang-sierra-type-size = { version = "2.12.0-dev.0", default-features = false }
Expand All @@ -26,6 +26,14 @@ assert_matches = "1.5.0"
rstest = "0.17.0"
num-traits = { version = "0.2", default-features = false }
num-bigint.workspace = true
getrandom = { version = "0.2.16", features = ["js"]}

[features]
default = ["std"]
mod_builtin = ["cairo-vm/mod_builtin"]
std = ["cairo-vm/std"]

[[bin]]
name = "cairo1-run"
path = "./src/main.rs"
required-features = ["std"]
4 changes: 2 additions & 2 deletions cairo1-run/src/cairo_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use cairo_vm::{
hint_processor::cairo_1_hint_processor::hint_processor::Cairo1HintProcessor,
math_utils::signed_felt,
serde::deserialize_program::{ApTracking, FlowTrackingData, HintParams, ReferenceManager},
stdlib::{collections::HashMap, iter::Peekable},
types::{
builtin_name::BuiltinName, layout::CairoLayoutParams, layout_name::LayoutName,
program::Program, relocatable::MaybeRelocatable,
Expand All @@ -52,7 +53,6 @@ use cairo_vm::{
use itertools::{chain, Itertools};
use num_bigint::{BigInt, Sign};
use num_traits::{cast::ToPrimitive, Zero};
use std::{collections::HashMap, iter::Peekable};

/// Representation of a cairo argument
/// Can consist of a single Felt or an array of Felts
Expand Down Expand Up @@ -616,7 +616,7 @@ fn create_entry_code(
} else if generic_ty == &GasBuiltinType::ID {
// Load initial gas
casm_build_extend! {ctx,
const initial_gas = 9999999999999_usize;
const initial_gas = 9999999999999_u64;
tempvar gas = initial_gas;
};
} else {
Expand Down
31 changes: 31 additions & 0 deletions examples/wasm-demo-cairo1/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "wasm-demo-cairo1"
description = "A demo using cairo-vm in a WASM environment"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme = "README.md"
keywords.workspace = true
publish = false

[lib]
crate-type = ["cdylib", "rlib"]

[features]
default = ["console_error_panic_hook"]

[dependencies]
wasm-bindgen = "0.2.100"

# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.6", optional = true }

serde_json = { workspace = true }

cairo-lang-sierra = { workspace = true }
cairo-vm = { workspace = true }
cairo1-run = { path = "../../cairo1-run", default-features = false }
59 changes: 59 additions & 0 deletions examples/wasm-demo-cairo1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Demo of `cairo-vm` on WebAssembly (Cairo 1)

While cairo-vm is compatible with WebAssembly, it doesn't implement any bindings to it.
Instead, create a new WebAssembly crate with cairo-vm and cairo1-run as dependencies and implement the required functionality there.

Since mimalloc is not automatically compilable to WebAssembly, the cairo-vm dependency should disable the default features, which will in turn disable mimalloc. Simliar to this, WebAssembly is
not compatible with rust standard library. For this reason, cairo1-run should also disable the default features.

A working example is provided in this repository.

## Dependencies

To compile and run the example you need:

- a Cairo 1 or Cairo 2 compiler
- the _wasm-pack_ crate
- some HTTP server (for example: the `live-server` npm module)

> **Note**
> The first two dependencies can be installed via the repository's installation script (see ["Installation script"](../../README.md#installation-script))

## Building

To build the example, first you need to compile your Cairo Program, using either cairo 1 or cairo 2 compiler:

If cairo 1 is used:

```sh
cairo-compile -rs ../../cairo_programs/cairo-1-programs/bitwise.cairo ../../cairo_programs/cairo-1-programs/bitwise.sierra
```

If cairo 2 is used:

```sh
cairo-compile -r ../../cairo_programs/cairo-1-programs/bitwise.cairo ../../cairo_programs/cairo-1-programs/bitwise.sierra
```

> WARNING: This example uses `cairo1-run::cairo_run_program` which expectes the program to be compiled with debug names. By default, `cairo-compile` does not include debug names in sierra. Due to this, the flag `-r` or `--replace-ids` is needed.

compile the WebAssembly package:

```sh
wasm-pack build --target=web
```

This will generate a javascript module that is directly loadable by the browser.

## Running

To run the example webpage, you need to run an HTTP server.
For example, using the _live-server_ npm module:

```sh
# while in <repo>/examples/wasm-demo-cairo1
npx live-server
```

> **Warning**
> Trying to run `index.html` directly (i.e. URL starts with `file://`) will result in a CORS error.
12 changes: 12 additions & 0 deletions examples/wasm-demo-cairo1/bitwise.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
fn main() -> u128 {
let a = 1234_u128;
let b = 5678_u128;

let c0 = a & b;
let c1 = a ^ b;
let c2 = a | b;

let c3 = c0 + c1 + c2;

c3
}
30 changes: 30 additions & 0 deletions examples/wasm-demo-cairo1/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Cairo WebAssembly Demo with Cairo 1</title>

<script type="module">
import init, { runCairoProgram } from './pkg/wasm_demo_cairo1.js';

// Initialize WebAssembly module.
// Note: This calls the `start()` function automatically.
await init();

// Run cairo-rs through our proxy function.
const value = await runCairoProgram();

// Display the result.
document.getElementById('result').innerHTML += value;
</script>
</head>

<body>
<p id="result">Result: </p>
</body>

</html>
50 changes: 50 additions & 0 deletions examples/wasm-demo-cairo1/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
mod utils;

use cairo1_run::Cairo1RunConfig;
use cairo_lang_sierra::ProgramParser;
use cairo_vm::types::layout_name::LayoutName;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(msg: &str);
}

#[wasm_bindgen(start)]
pub fn start() {
crate::utils::set_panic_hook();
}

macro_rules! wrap_error {
($xp: expr) => {
$xp.map_err(|e| JsValue::from_str(&format!("Error from CairoRunner: {}", e.to_string())))
};
}

#[wasm_bindgen(js_name = runCairoProgram)]
pub fn run_cairo_program() -> Result<String, JsValue> {
let cairo_run_config = Cairo1RunConfig {
layout: LayoutName::all_cairo,
relocate_mem: true,
trace_enabled: true,
serialize_output: true,
..Default::default()
};

let sierra_program = {
let program_str = include_str!("../../../cairo_programs/cairo-1-programs/bitwise.sierra");
wrap_error!(ProgramParser::new().parse(program_str))?
};

let (_, _, serialized_output) = wrap_error!(cairo1_run::cairo_run_program(
&sierra_program,
cairo_run_config
))?;

let output = serialized_output.unwrap();

log(&output);

Ok(output)
}
10 changes: 10 additions & 0 deletions examples/wasm-demo-cairo1/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
pub fn set_panic_hook() {
// When the `console_error_panic_hook` feature is enabled, we can call the
// `set_panic_hook` function at least once during initialization, and then
// we will get better error messages if our code ever panics.
//
// For more details see
// https://github.com/rustwasm/console_error_panic_hook#readme
#[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once();
}
2 changes: 1 addition & 1 deletion examples/wasm-demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Cairo WebAssembly Demo</title>
<title>Cairo WebAssembly Demo with Cairo 0</title>

<script type="module">
import init, { runCairoProgram } from './pkg/wasm_demo.js';
Expand Down
Loading