diff --git a/.cargo/config.toml b/.cargo/config.toml index 830425f410..3e7c829b0a 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,4 +1,5 @@ [env] +CAIRO_NATIVE_RUNTIME_LIBRARY = "./libcairo_native_runtime.a" LLVM_SYS_191_PREFIX = "/usr/lib/llvm-19/" MLIR_SYS_190_PREFIX = "/usr/lib/llvm-19/" TABLEGEN_190_PREFIX = "/usr/lib/llvm-19/" diff --git a/.github/workflows/blockifier_ci.yml b/.github/workflows/blockifier_ci.yml index a38152d4f0..ec3655e2bf 100644 --- a/.github/workflows/blockifier_ci.yml +++ b/.github/workflows/blockifier_ci.yml @@ -44,6 +44,10 @@ jobs: runs-on: starkware-ubuntu-20-04-medium steps: - uses: actions/checkout@v4 + with: + # required to clone native as a gitsubmodule + submodules: recursive + fetch-depth: 0 - uses: ./.github/actions/bootstrap # No features - build blockifier without features activated by dependencies in the workspace. - run: cargo build -p blockifier @@ -51,6 +55,6 @@ jobs: # transaction_serde is not activated by any workspace crate; test the build. - run: cargo build -p blockifier --features transaction_serde - run: cargo test -p blockifier --features transaction_serde - # cairo_native is not activated by any workspace crate; test the build. + # cairo_native is not activated by any workspace crate; test the build. - run: cargo build -p blockifier --features cairo_native - run: cargo test -p blockifier --features cairo_native diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4c846cd17a..72d8e43430 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,6 +31,8 @@ jobs: # Environment setup. - uses: actions/checkout@v4 with: + # required to clone native as a git submodule + submodules: recursive # Fetch the entire history. Required to checkout the merge target commit, so the diff can # be computed. fetch-depth: 0 diff --git a/.gitignore b/.gitignore index cab3c61de7..86d3bfa13c 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ scripts/papyrus/p2p_sync_e2e_test/data_server/ # Papyrus helm chart deployments/papyrus/helm/config/* !deployments/papyrus/helm/config/example.json + +# Generated file used for running contracts compiled with Cairo Native +crates/blockifier/libcairo_native_runtime.a diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..8ce19f6d3e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "crates/blockifier/cairo_native"] + path = crates/blockifier/cairo_native + url = https://github.com/lambdaclass/cairo_native diff --git a/Cargo.toml b/Cargo.toml index 22435f32ab..f418a81467 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,6 +96,7 @@ cairo-lang-sierra = "=2.8.4" cairo-lang-sierra-to-casm = "2.8.4" cairo-lang-starknet-classes = "2.8.4" cairo-lang-utils = "2.8.4" +# Important: when updated, make sure to update the cairo-native submodule as well. cairo-native = "0.2.0-alpha.4" cairo-vm = "=1.0.1" camelpaste = "0.1.0" diff --git a/crates/blockifier/build.rs b/crates/blockifier/build.rs new file mode 100644 index 0000000000..1a45e506bc --- /dev/null +++ b/crates/blockifier/build.rs @@ -0,0 +1,68 @@ +use std::path::PathBuf; +use std::process::Command; + +fn compile_cairo_native_aot_runtime() { + let cairo_native_dir = std::env::current_dir() + .expect("Failed to get current directory") + .join(PathBuf::from("cairo_native")); + + if !cairo_native_dir.exists() || !cairo_native_dir.join(".git").exists() { + panic!( + "It seems git submodule at {} doesn't exist or it is not initialized, please \ + run:\n\ngit submodule update --init --recursive\n", + cairo_native_dir.to_str().unwrap() + ); + } + + let runtime_target_dir = cairo_native_dir.join(PathBuf::from("target")); + let status = Command::new("cargo") + .args([ + "build", + "--release", + "-p", + "cairo-native-runtime", + "--message-format=json", + "--target-dir", + runtime_target_dir.to_str().unwrap(), + ]) + .current_dir(cairo_native_dir) + .status() + .expect("Failed to execute cargo"); + if !status.success() { + panic!("Building cairo native runtime failed: {status}") + } + + let runtime_target_path = + runtime_target_dir.join(PathBuf::from("release/libcairo_native_runtime.a")); + + const RUNTIME_LIBRARY: &str = "CAIRO_NATIVE_RUNTIME_LIBRARY"; + let runtime_expected_path = { + let expected_path_env = + std::env::var(RUNTIME_LIBRARY).expect("Cairo Native rutime path variable is not set"); + let expected_path = PathBuf::from(&expected_path_env); + + if expected_path.is_absolute() { + expected_path + } else { + std::env::current_dir().expect("Failed to get current directory").join(expected_path) + } + }; + + std::fs::copy(&runtime_target_path, &runtime_expected_path) + .expect("Failed to copy native runtime"); + + println!("cargo::rerun-if-changed=./cairo_native/runtime/"); + // todo(rodrigo): this directive seems to cause the build script to trigger everytime on + // Linux based machines. Investigate the issue further. + println!("cargo::rerun-if-changed={}", runtime_expected_path.to_str().unwrap()); + println!("cargo::rerun-if-env-changed={RUNTIME_LIBRARY}"); +} + +fn main() { + // `CARGO_FEATURE_CAIRO_NATIVE` env var is set by Cargo when compiling with the `cairo_native` + // feature flag. Build instructions are defined behind this condition since they are only + // relevant when using Cairo Native. + if std::env::var("CARGO_FEATURE_CAIRO_NATIVE").is_ok() { + compile_cairo_native_aot_runtime(); + } +} diff --git a/crates/blockifier/cairo_native b/crates/blockifier/cairo_native new file mode 160000 index 0000000000..b5769e4f6b --- /dev/null +++ b/crates/blockifier/cairo_native @@ -0,0 +1 @@ +Subproject commit b5769e4f6ba914b36eef68e0b1f71c791d7d075c diff --git a/taplo.toml b/taplo.toml index 9b57998302..58df6262cd 100644 --- a/taplo.toml +++ b/taplo.toml @@ -1,4 +1,7 @@ -exclude = ["crates/native_blockifier/.cargo/config.toml"] +exclude = [ + "crates/blockifier/cairo_native/**/*.toml", + "crates/native_blockifier/.cargo/config.toml", +] [formatting] column_width = 100