From 5dd9068b73c99d9ff860d5faec21f020cd5be9ef Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 12:50:19 -0300 Subject: [PATCH 01/37] First draft --- Cargo.lock | 236 +++++++++++++++++++++++++++++++++ cairo-vm-cli/src/main.rs | 18 +++ vm/Cargo.toml | 1 + vm/src/vm/runners/cairo_pie.rs | 37 ++++++ 4 files changed, 292 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 7b162d25f9..4c72f36e19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,23 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aes" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.7.7" @@ -200,6 +217,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bincode" version = "2.0.0-rc.3" @@ -269,6 +292,33 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cairo-felt" version = "0.8.7" @@ -722,6 +772,7 @@ dependencies = [ "starknet-types-core", "thiserror-no-std", "wasm-bindgen-test", + "zip", ] [[package]] @@ -772,6 +823,7 @@ version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ + "jobserver", "libc", ] @@ -808,6 +860,16 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "4.4.8" @@ -901,6 +963,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "convert_case" version = "0.6.0" @@ -919,6 +987,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "criterion" version = "0.5.1" @@ -1015,6 +1092,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1124,6 +1210,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1414,6 +1510,15 @@ version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" @@ -1458,6 +1563,15 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "jobserver" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.65" @@ -1639,6 +1753,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "ndarray" version = "0.13.1" @@ -1832,6 +1955,17 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + [[package]] name = "paste" version = "1.0.14" @@ -1844,6 +1978,18 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", + "hmac", + "password-hash", + "sha2", +] + [[package]] name = "petgraph" version = "0.6.4" @@ -1881,6 +2027,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" + [[package]] name = "plotters" version = "0.3.5" @@ -1909,6 +2061,12 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2336,6 +2494,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.8" @@ -2589,6 +2758,24 @@ dependencies = [ "thiserror-impl-no-std", ] +[[package]] +name = "time" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +dependencies = [ + "deranged", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -3010,3 +3197,52 @@ dependencies = [ "quote", "syn 2.0.39", ] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index a24ef7bb92..a7d8497169 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -42,6 +42,8 @@ struct Args { air_public_input: Option<String>, #[clap(long = "air_private_input")] air_private_input: Option<String>, + #[clap(long = "cairo_pie_output")] + cairo_pie_output: Option<String>, } fn validate_layout(value: &str) -> Result<String, String> { @@ -145,6 +147,14 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { return Err(Error::Cli(error)); } + if args.cairo_pie_output.is_some() && args.proof_mode { + let error = Args::command().error( + clap::error::ErrorKind::ArgumentConflict, + "--proof_mode and --cairo_pie_output cannot be both specified.", + ); + return Err(Error::Cli(error)); + } + let trace_enabled = args.trace_file.is_some() || args.air_public_input.is_some(); let mut hint_executor = BuiltinHintProcessor::new_empty(); let cairo_run_config = cairo_run::CairoRunConfig { @@ -227,6 +237,14 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { std::fs::write(file_path, json)?; } + if let Some(file_name) = args.cairo_pie_output { + cairo_runner + .get_cairo_pie(&vm) + .map_err(CairoRunError::Runner)? + .write_zip_file(&file_name) + .unwrap() + } + Ok(()) } diff --git a/vm/Cargo.toml b/vm/Cargo.toml index e7f9fe029a..a7af63173d 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -42,6 +42,7 @@ extensive_hints = [] print = ["std"] [dependencies] +zip = "0.6.6" mimalloc = { workspace = true, optional = true } num-bigint = { workspace = true } rand = { workspace = true } diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index d464065899..7e9128ac76 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -1,3 +1,5 @@ +use std::{fs::File, io::Write, path::Path}; + use super::cairo_runner::ExecutionResources; use crate::{ serde::deserialize_program::BuiltinName, @@ -6,6 +8,7 @@ use crate::{ Felt252, }; use serde::{Deserialize, Serialize}; +use zip::ZipWriter; const CAIRO_PIE_VERSION: &str = "1.1"; @@ -96,6 +99,40 @@ pub struct CairoPieVersion { pub cairo_pie: (), } +impl CairoPie { + pub fn serialize_json(&self) -> Result<String, serde_json::Error> { + serde_json::to_string_pretty(&self) + } + + pub fn write_zip_file(&self, file_name: &String) -> Result<(), std::io::Error> { + let path = Path::new(file_name); + let file = File::create(path).unwrap(); + let mut zip_writer = ZipWriter::new(file); + let options = + zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Stored); + zip_writer.start_file("version.json", options)?; + zip_writer.write(serde_json::to_string(&self.version).unwrap().as_bytes())?; + zip_writer.start_file("metadata.json", options)?; + zip_writer.write(serde_json::to_string(&self.metadata).unwrap().as_bytes())?; + zip_writer.start_file("memory.bin", options)?; + zip_writer.write(serde_json::to_string(&self.memory).unwrap().as_bytes())?; + zip_writer.start_file("additional_data.json", options)?; + zip_writer.write( + serde_json::to_string(&self.additional_data) + .unwrap() + .as_bytes(), + )?; + zip_writer.start_file("execution_resources.json", options)?; + zip_writer.write( + serde_json::to_string(&self.execution_resources) + .unwrap() + .as_bytes(), + )?; + zip_writer.finish().unwrap(); + Ok(()) + } +} + mod serde_impl { use super::CAIRO_PIE_VERSION; use crate::{types::relocatable::MaybeRelocatable, utils::CAIRO_PRIME, Felt252}; From 7a9924e0cf295defcd07c0afd616b0a17e852be9 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 13:37:28 -0300 Subject: [PATCH 02/37] Add special serialization for ecdsa builtin additional data --- vm/src/vm/runners/cairo_pie.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index 7e9128ac76..ef94620157 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -55,6 +55,7 @@ pub enum BuiltinAdditionalData { Hash(Vec<Relocatable>), Output(OutputBuiltinAdditionalData), // Signatures are composed of (r, s) tuples + #[serde(serialize_with = "serde_impl::serialize_signature_additional_data")] Signature(HashMap<Relocatable, (Felt252, Felt252)>), None, } @@ -134,11 +135,20 @@ impl CairoPie { } mod serde_impl { + use std::collections::HashMap; + use super::CAIRO_PIE_VERSION; - use crate::{types::relocatable::MaybeRelocatable, utils::CAIRO_PRIME, Felt252}; + use crate::{ + types::relocatable::{MaybeRelocatable, Relocatable}, + utils::CAIRO_PRIME, + Felt252, + }; use num_bigint::BigUint; use num_traits::Num; - use serde::{ser::SerializeSeq, Serialize, Serializer}; + use serde::{ + ser::{SerializeMap, SerializeSeq}, + Serialize, Serializer, + }; pub const ADDR_BYTE_LEN: usize = 8; pub const FIELD_BYTE_LEN: usize = 32; @@ -253,6 +263,21 @@ mod serde_impl { { serializer.serialize_str(CAIRO_PIE_VERSION) } + + pub fn serialize_signature_additional_data<S>( + values: &HashMap<Relocatable, (Felt252, Felt252)>, + serializer: S, + ) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + let mut map_serializer = serializer.serialize_map(Some(values.len()))?; + + for (key, (x, y)) in values { + map_serializer.serialize_entry(&key.to_string(), &format!("[{}, {}]", x, y))?; + } + map_serializer.end() + } } #[cfg(test)] From 653e8b04a772567ee5d60ca7d36c99258b1537f1 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 13:38:57 -0300 Subject: [PATCH 03/37] Start comparison script --- Makefile | 14 ++++++++++---- vm/src/tests/cairo_pie_comparator.py | 20 ++++++++++++++++++++ vm/src/tests/compare_vm_state.sh | 14 ++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 vm/src/tests/cairo_pie_comparator.py diff --git a/Makefile b/Makefile index e39d995130..4ebc32d0ce 100644 --- a/Makefile +++ b/Makefile @@ -69,8 +69,10 @@ TEST_FILES:=$(wildcard $(TEST_DIR)/*.cairo) COMPILED_TESTS:=$(patsubst $(TEST_DIR)/%.cairo, $(TEST_DIR)/%.json, $(TEST_FILES)) CAIRO_MEM:=$(patsubst $(TEST_DIR)/%.json, $(TEST_DIR)/%.memory, $(COMPILED_TESTS)) CAIRO_TRACE:=$(patsubst $(TEST_DIR)/%.json, $(TEST_DIR)/%.trace, $(COMPILED_TESTS)) +CAIRO_PIE:=$(patsubst $(TEST_DIR)/%.json, $(TEST_DIR)/%.pie.zip, $(COMPILED_TESTS)) CAIRO_RS_MEM:=$(patsubst $(TEST_DIR)/%.json, $(TEST_DIR)/%.rs.memory, $(COMPILED_TESTS)) CAIRO_RS_TRACE:=$(patsubst $(TEST_DIR)/%.json, $(TEST_DIR)/%.rs.trace, $(COMPILED_TESTS)) +CAIRO_RS_PIE:=$(patsubst $(TEST_DIR)/%.json, $(TEST_DIR)/%.rs.pie.zip, $(COMPILED_TESTS)) BENCH_DIR=cairo_programs/benchmarks BENCH_FILES:=$(wildcard $(BENCH_DIR)/*.cairo) @@ -94,11 +96,11 @@ $(BENCH_DIR)/%.json: $(BENCH_DIR)/%.cairo $(TEST_DIR)/%.json: $(TEST_DIR)/%.cairo cairo-compile --cairo_path="$(TEST_DIR):$(BENCH_DIR)" $< --output $@ -$(TEST_DIR)/%.rs.trace $(TEST_DIR)/%.rs.memory: $(TEST_DIR)/%.json $(RELBIN) - cargo llvm-cov run -p cairo-vm-cli --release --no-report -- --layout all_cairo $< --trace_file $@ --memory_file $(@D)/$(*F).rs.memory +$(TEST_DIR)/%.rs.trace $(TEST_DIR)/%.rs.memory $(TEST_DIR)/%.rs.pie.zip: $(TEST_DIR)/%.json $(RELBIN) + cargo llvm-cov run -p cairo-vm-cli --release --no-report -- --layout all_cairo $< --trace_file $@ --memory_file $(@D)/$(*F).rs.memory --cairo_pie_output $(@D)/$(*F).rs.pie.zip -$(TEST_DIR)/%.trace $(TEST_DIR)/%.memory: $(TEST_DIR)/%.json - cairo-run --layout starknet_with_keccak --program $< --trace_file $@ --memory_file $(@D)/$(*F).memory +$(TEST_DIR)/%.trace $(TEST_DIR)/%.memory $(TEST_DIR)/%.pie.zip: $(TEST_DIR)/%.json + cairo-run --layout starknet_with_keccak --program $< --trace_file $@ --memory_file $(@D)/$(*F).memory --cairo_pie_output $(@D)/$(*F).pie.zip $(NORETROCOMPAT_DIR)/%.json: $(NORETROCOMPAT_DIR)/%.cairo cairo-compile --cairo_path="$(TEST_DIR):$(BENCH_DIR):$(NORETROCOMPAT_DIR)" $< --output $@ @@ -306,6 +308,9 @@ compare_air_public_input: $(CAIRO_RS_AIR_PUBLIC_INPUT) $(CAIRO_AIR_PUBLIC_INPUT) compare_air_private_input: $(CAIRO_RS_AIR_PRIVATE_INPUT) $(CAIRO_AIR_PRIVATE_INPUT) cd vm/src/tests; ./compare_vm_state.sh memory proof_mode air_private_input +compare_pie: $(CAIRO_RS_PIE) $(CAIRO_PIE) + cd vm/src/tests; ./compare_vm_state.sh pie + # Run with nightly enable the `doc_cfg` feature wich let us provide clear explaination about which parts of the code are behind a feature flag docs: RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --verbose --release --locked --no-deps --all-features --open @@ -314,6 +319,7 @@ clean: rm -f $(TEST_DIR)/*.json rm -f $(TEST_DIR)/*.memory rm -f $(TEST_DIR)/*.trace + rm -f $(TEST_DIR)/*.pie.zip rm -f $(BENCH_DIR)/*.json rm -f $(BAD_TEST_DIR)/*.json rm -f $(PRINT_TEST_DIR)/*.json diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py new file mode 100644 index 0000000000..8156a173cb --- /dev/null +++ b/vm/src/tests/cairo_pie_comparator.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +import sys +import json +from zipfile import ZipFile + + +filename1 = sys.argv[1] +filename2 = sys.argv[2] + +with ZipFile(filename1) as cairo_lang_pie_zip, ZipFile(filename2) as cairo_vm_pie_zip: + with cairo_lang_pie_zip.open('version.json') as cl_verison_file, cairo_vm_pie_zip.open('version.json') as cv_verison_file: + cl_version = json.load(cl_verison_file) + cv_version = json.load(cv_verison_file) + if cl_version == cv_verison_file: + print(f"Comparison succesful for {filename1}/version.json vs {filename2}/version.json") + else: + print(f"Comparison unsuccesful for {filename1}/version.json vs {filename2}/version.json") + exit(1) + diff --git a/vm/src/tests/compare_vm_state.sh b/vm/src/tests/compare_vm_state.sh index 24388d20bf..34c7486663 100755 --- a/vm/src/tests/compare_vm_state.sh +++ b/vm/src/tests/compare_vm_state.sh @@ -10,6 +10,7 @@ trace=false memory=false air_public_input=false air_private_input=false +pie=false passed_tests=0 failed_tests=0 @@ -30,6 +31,9 @@ for i in $@; do "air_private_input") air_private_input=true echo "Requested air_private_input comparison" ;; + "pie") pie=true + echo "Requested pie comparison" + ;; *) ;; esac @@ -90,6 +94,16 @@ for file in $(ls $tests_path | grep .cairo$ | sed -E 's/\.cairo$//'); do passed_tests=$((passed_tests + 1)) fi fi + + if $pie; then + if ! ./cairo_pie_comparator.py $path_file.pie.zip $path_file.rs.pie.zip; then + echo "Cairo PIE differs for $file" + exit_code=1 + failed_tests=$((failed_tests + 1)) + else + passed_tests=$((passed_tests + 1)) + fi + fi done if test $failed_tests != 0; then From 666f6e80c7dad25a1691724a160400ee2d7cb11d Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 13:53:38 -0300 Subject: [PATCH 04/37] Add compare_all_no_proof target --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4ebc32d0ce..887955c5f5 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ endif .PHONY: build-cairo-1-compiler build-cairo-1-compiler-macos build-cairo-2-compiler build-cairo-2-compiler-macos \ deps deps-macos cargo-deps build run check test clippy coverage benchmark \ compare_benchmarks_deps compare_benchmarks docs clean \ - compare_vm_output compare_trace_memory compare_trace compare_memory \ + compare_trace_memory compare_trace compare_memory compare_pie compare_all_no_proof \ compare_trace_memory_proof compare_all_proof compare_trace_proof compare_memory_proof compare_air_public_input compare_air_private_input\ cairo_bench_programs cairo_proof_programs cairo_test_programs cairo_1_test_contracts cairo_2_test_contracts \ cairo_trace cairo-vm_trace cairo_proof_trace cairo-vm_proof_trace \ @@ -284,6 +284,9 @@ compare_benchmarks: cairo_bench_programs compare_trace_memory: $(CAIRO_RS_TRACE) $(CAIRO_TRACE) $(CAIRO_RS_MEM) $(CAIRO_MEM) cd vm/src/tests; ./compare_vm_state.sh trace memory +compare_all_no_proof: $(CAIRO_RS_TRACE) $(CAIRO_TRACE) $(CAIRO_RS_MEM) $(CAIRO_MEM) $(CAIRO_RS_PIE) $(CAIRO_PIE) + cd vm/src/tests; ./compare_vm_state.sh trace memory + compare_trace: $(CAIRO_RS_TRACE) $(CAIRO_TRACE) cd vm/src/tests; ./compare_vm_state.sh trace From 5a724985ecc895134b452a84dd1ebf8c628addce Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 13:54:05 -0300 Subject: [PATCH 05/37] Update file permissions --- vm/src/tests/cairo_pie_comparator.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 vm/src/tests/cairo_pie_comparator.py diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py old mode 100644 new mode 100755 From 89a7af054586ea43e6811e4875fd555864acf076 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 14:13:32 -0300 Subject: [PATCH 06/37] Fix makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 887955c5f5..3c60039b59 100644 --- a/Makefile +++ b/Makefile @@ -97,10 +97,10 @@ $(TEST_DIR)/%.json: $(TEST_DIR)/%.cairo cairo-compile --cairo_path="$(TEST_DIR):$(BENCH_DIR)" $< --output $@ $(TEST_DIR)/%.rs.trace $(TEST_DIR)/%.rs.memory $(TEST_DIR)/%.rs.pie.zip: $(TEST_DIR)/%.json $(RELBIN) - cargo llvm-cov run -p cairo-vm-cli --release --no-report -- --layout all_cairo $< --trace_file $@ --memory_file $(@D)/$(*F).rs.memory --cairo_pie_output $(@D)/$(*F).rs.pie.zip + cargo llvm-cov run -p cairo-vm-cli --release --no-report -- --layout all_cairo $< --trace_file $(@D)/$(*F) --memory_file $(@D)/$(*F).rs.memory --cairo_pie_output $(@D)/$(*F).rs.pie.zip $(TEST_DIR)/%.trace $(TEST_DIR)/%.memory $(TEST_DIR)/%.pie.zip: $(TEST_DIR)/%.json - cairo-run --layout starknet_with_keccak --program $< --trace_file $@ --memory_file $(@D)/$(*F).memory --cairo_pie_output $(@D)/$(*F).pie.zip + cairo-run --layout starknet_with_keccak --program $< --trace_file $(@D)/$(*F) --memory_file $(@D)/$(*F).memory --cairo_pie_output $(@D)/$(*F).pie.zip $(NORETROCOMPAT_DIR)/%.json: $(NORETROCOMPAT_DIR)/%.cairo cairo-compile --cairo_path="$(TEST_DIR):$(BENCH_DIR):$(NORETROCOMPAT_DIR)" $< --output $@ From 5bcf06a8faf21263b4ab107eca2c4b18a155eed7 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 16:13:01 -0300 Subject: [PATCH 07/37] Add special serialization for pedersen builtin additional data --- vm/src/vm/runners/cairo_pie.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index ef94620157..d780341ef7 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -52,6 +52,7 @@ pub struct OutputBuiltinAdditionalData { #[serde(untagged)] pub enum BuiltinAdditionalData { // Contains verified addresses as contiguous index, value pairs + #[serde(serialize_with = "serde_impl::serialize_hash_additional_data")] Hash(Vec<Relocatable>), Output(OutputBuiltinAdditionalData), // Signatures are composed of (r, s) tuples @@ -278,6 +279,23 @@ mod serde_impl { } map_serializer.end() } + + pub fn serialize_hash_additional_data<S>( + values: &[Relocatable], + serializer: S, + ) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + let mut seq_serializer = serializer.serialize_seq(Some(values.len()))?; + + for value in values { + seq_serializer + .serialize_element(&format!("[{}, {}]", value.segment_index, value.offset))?; + } + + seq_serializer.end() + } } #[cfg(test)] From b429d33354c8a7e8e991388f312c3c5f4da70ade Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 16:22:19 -0300 Subject: [PATCH 08/37] Fix prev commit --- vm/src/vm/runners/cairo_pie.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index d780341ef7..bcb1cbe643 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -291,7 +291,7 @@ mod serde_impl { for value in values { seq_serializer - .serialize_element(&format!("[{}, {}]", value.segment_index, value.offset))?; + .serialize_element(&[value.segment_index, value.offset as isize])?; } seq_serializer.end() From 9a6fcbe44903dcef1dbc6048a10103685dc73a8f Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 16:35:06 -0300 Subject: [PATCH 09/37] Serialize ecdsa additional data as sequence --- vm/src/vm/runners/cairo_pie.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index bcb1cbe643..b8270504bb 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -146,10 +146,7 @@ mod serde_impl { }; use num_bigint::BigUint; use num_traits::Num; - use serde::{ - ser::{SerializeMap, SerializeSeq}, - Serialize, Serializer, - }; + use serde::{ser::SerializeSeq, Serialize, Serializer}; pub const ADDR_BYTE_LEN: usize = 8; pub const FIELD_BYTE_LEN: usize = 32; @@ -272,12 +269,18 @@ mod serde_impl { where S: Serializer, { - let mut map_serializer = serializer.serialize_map(Some(values.len()))?; + let mut seq_serializer = serializer.serialize_seq(Some(values.len()))?; for (key, (x, y)) in values { - map_serializer.serialize_entry(&key.to_string(), &format!("[{}, {}]", x, y))?; + seq_serializer.serialize_element(&[ + [ + Felt252Wrapper(&Felt252::from(key.segment_index)), + Felt252Wrapper(&Felt252::from(key.offset)), + ], + [Felt252Wrapper(x), Felt252Wrapper(y)], + ])?; } - map_serializer.end() + seq_serializer.end() } pub fn serialize_hash_additional_data<S>( @@ -290,8 +293,7 @@ mod serde_impl { let mut seq_serializer = serializer.serialize_seq(Some(values.len()))?; for value in values { - seq_serializer - .serialize_element(&[value.segment_index, value.offset as isize])?; + seq_serializer.serialize_element(&[value.segment_index, value.offset as isize])?; } seq_serializer.end() From 3d17276871a5b004e8dba788065f89b97d71a50a Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 16:43:23 -0300 Subject: [PATCH 10/37] Expand comparison script --- vm/src/tests/cairo_pie_comparator.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py index 8156a173cb..ae402623cc 100755 --- a/vm/src/tests/cairo_pie_comparator.py +++ b/vm/src/tests/cairo_pie_comparator.py @@ -8,13 +8,16 @@ filename1 = sys.argv[1] filename2 = sys.argv[2] -with ZipFile(filename1) as cairo_lang_pie_zip, ZipFile(filename2) as cairo_vm_pie_zip: - with cairo_lang_pie_zip.open('version.json') as cl_verison_file, cairo_vm_pie_zip.open('version.json') as cv_verison_file: - cl_version = json.load(cl_verison_file) - cv_version = json.load(cv_verison_file) - if cl_version == cv_verison_file: - print(f"Comparison succesful for {filename1}/version.json vs {filename2}/version.json") - else: - print(f"Comparison unsuccesful for {filename1}/version.json vs {filename2}/version.json") - exit(1) +strict_comparison_files = ["version.json", "metadata.json", "execution_resources.json", "additional_data.json"] +with ZipFile(filename1) as cairo_lang_pie_zip, ZipFile(filename2) as cairo_vm_pie_zip: + # Compare json files + for file in strict_comparison_files: + with cairo_lang_pie_zip.open(file) as cairo_lang_file, cairo_vm_pie_zip.open(file) as cairo_vm_file: + cl_content = json.load(cairo_lang_file) + cv_content = json.load(cairo_vm_file) + if cl_content == cv_content: + print(f"Comparison succesful for {filename1}/{file} vs {filename2}/{file}") + else: + print(f"Comparison unsuccesful for {filename1}/{file} vs {filename2}/{file}") + exit(1) From f9a449ef9c476572266497673c69fe7de4932179 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 16:56:20 -0300 Subject: [PATCH 11/37] Skip bugged case + Reduce amount of prints in comparison script --- vm/src/tests/cairo_pie_comparator.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py index ae402623cc..98c89b606f 100755 --- a/vm/src/tests/cairo_pie_comparator.py +++ b/vm/src/tests/cairo_pie_comparator.py @@ -13,11 +13,15 @@ with ZipFile(filename1) as cairo_lang_pie_zip, ZipFile(filename2) as cairo_vm_pie_zip: # Compare json files for file in strict_comparison_files: + # Skipping this check due to a bug in the memory holes count + # TODO: Remove it once the bug is fixed + if filename1 == "../../../cairo_programs/keccak_alternative_hint.pie.zip" and file == "execution_resources.json": + continue with cairo_lang_pie_zip.open(file) as cairo_lang_file, cairo_vm_pie_zip.open(file) as cairo_vm_file: cl_content = json.load(cairo_lang_file) cv_content = json.load(cairo_vm_file) - if cl_content == cv_content: - print(f"Comparison succesful for {filename1}/{file} vs {filename2}/{file}") - else: + if cl_content != cv_content: print(f"Comparison unsuccesful for {filename1}/{file} vs {filename2}/{file}") exit(1) + + print(f"Comparison succesful for {filename1} vs {filename2}") From 171862deb87ef66e47234bf8cdf37a78d758db22 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 17:07:02 -0300 Subject: [PATCH 12/37] Improve skip --- vm/src/tests/cairo_pie_comparator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py index 98c89b606f..4c6a34fd05 100755 --- a/vm/src/tests/cairo_pie_comparator.py +++ b/vm/src/tests/cairo_pie_comparator.py @@ -15,7 +15,8 @@ for file in strict_comparison_files: # Skipping this check due to a bug in the memory holes count # TODO: Remove it once the bug is fixed - if filename1 == "../../../cairo_programs/keccak_alternative_hint.pie.zip" and file == "execution_resources.json": + if (filename1 == "../../../cairo_programs/_keccak_alternative_hint.pie.zip" or filename1 == "../../../cairo_programs/relocate_temporary_segment_append.pie.zip") and file == "execution_resources.json": + print(f"Comparison skipped for {filename1}/{file} vs {filename2}/{file}") continue with cairo_lang_pie_zip.open(file) as cairo_lang_file, cairo_vm_pie_zip.open(file) as cairo_vm_file: cl_content = json.load(cairo_lang_file) From 89fc207ad96060c8007e588d815199d890118786 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 17:24:49 -0300 Subject: [PATCH 13/37] Add comparison to CI --- .github/workflows/rust.yml | 11 ++++++++--- vm/src/tests/cairo_pie_comparator.py | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 20c9ec31fc..54ed96ea0a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -322,6 +322,7 @@ jobs: cairo_programs/**/*.trace cairo_programs/**/*.air_public_input cairo_programs/**/*.air_private_input + cairo_programs/**/*.pie.zip key: ${{ matrix.program-target }}-reference-trace-cache-${{ hashFiles('cairo_programs/**/*.cairo', 'examples/wasm-demo/src/array_sum.cairo') }} restore-keys: ${{ matrix.program-target }}-reference-trace-cache- @@ -364,7 +365,7 @@ jobs: extra-args: '--proof_mode --air_public_input {program}.rs.air_public_input --air_private_input {program}.rs.air_private_input ' - program-target: cairo_test_programs programs-dir: cairo_programs - extra-args: '' + extra-args: '--cairo_pie_output {program}.rs.pie.zip' name: Compute memory and execution traces with cairo-vm needs: [ build-programs, build-release ] runs-on: ubuntu-22.04 @@ -401,6 +402,7 @@ jobs: cairo_programs/**/*.trace cairo_programs/**/*.air_public_input cairo_programs/**/*.air_private_input + cairo_programs/**/*.pie.zip key: ${{ matrix.program-target }}-release-trace-cache-${{ github.sha }} @@ -501,6 +503,7 @@ jobs: cairo_programs/**/*.trace cairo_programs/**/*.air_public_input cairo_programs/**/*.air_private_input + cairo_programs/**/*.pie.zip key: ${{ matrix.program-target }}-reference-trace-cache-${{ hashFiles('cairo_programs/**/*.cairo', 'examples/wasm-demo/src/array_sum.cairo') }} fail-on-cache-miss: true @@ -512,6 +515,7 @@ jobs: cairo_programs/**/*.trace cairo_programs/**/*.air_public_input cairo_programs/**/*.air_private_input + cairo_programs/**/*.pie.zip key: ${{ matrix.program-target }}-release-trace-cache-${{ github.sha }} fail-on-cache-miss: true @@ -521,9 +525,10 @@ jobs: PROOF=proof_mode AIR_PUBLIC_INPUT=air_public_input AIR_PRIVATE_INPUT=air_private_input + else + PIE=pie fi - ./vm/src/tests/compare_vm_state.sh trace memory $PROOF $AIR_PUBLIC_INPUT $AIR_PRIVATE_INPUT - ./vm/src/tests/compare_vm_state.sh trace memory $PROOF + ./vm/src/tests/compare_vm_state.sh trace memory $PROOF $AIR_PUBLIC_INPUT $AIR_PRIVATE_INPUT $PIE wasm-demo: name: Build the wasm demo diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py index 4c6a34fd05..8cf2934ef9 100755 --- a/vm/src/tests/cairo_pie_comparator.py +++ b/vm/src/tests/cairo_pie_comparator.py @@ -15,7 +15,7 @@ for file in strict_comparison_files: # Skipping this check due to a bug in the memory holes count # TODO: Remove it once the bug is fixed - if (filename1 == "../../../cairo_programs/_keccak_alternative_hint.pie.zip" or filename1 == "../../../cairo_programs/relocate_temporary_segment_append.pie.zip") and file == "execution_resources.json": + if (filename1 == "../../../cairo_programs/_keccak_alternative_hint.pie.zip" or filename1 == "../../../cairo_programs/relocate_temporary_segment_append.pie.zip" or filename1 == "../../../cairo_programs/_keccak_alternative_hint.pie.zip") and file == "execution_resources.json": print(f"Comparison skipped for {filename1}/{file} vs {filename2}/{file}") continue with cairo_lang_pie_zip.open(file) as cairo_lang_file, cairo_vm_pie_zip.open(file) as cairo_vm_file: From a0c74c91d8bc1e0c514d93ab984870923970907c Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 17:30:46 -0300 Subject: [PATCH 14/37] Fix --- vm/src/tests/cairo_pie_comparator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py index 8cf2934ef9..ea678a2bc4 100755 --- a/vm/src/tests/cairo_pie_comparator.py +++ b/vm/src/tests/cairo_pie_comparator.py @@ -4,7 +4,6 @@ import json from zipfile import ZipFile - filename1 = sys.argv[1] filename2 = sys.argv[2] @@ -15,7 +14,7 @@ for file in strict_comparison_files: # Skipping this check due to a bug in the memory holes count # TODO: Remove it once the bug is fixed - if (filename1 == "../../../cairo_programs/_keccak_alternative_hint.pie.zip" or filename1 == "../../../cairo_programs/relocate_temporary_segment_append.pie.zip" or filename1 == "../../../cairo_programs/_keccak_alternative_hint.pie.zip") and file == "execution_resources.json": + if (filename1 == "../../../cairo_programs/_keccak_alternative_hint.pie.zip" or filename1 == "../../../cairo_programs/relocate_temporary_segment_append.pie.zip" or filename1 == "../../../cairo_programs/keccak_alternative_hint.pie.zip") and file == "execution_resources.json": print(f"Comparison skipped for {filename1}/{file} vs {filename2}/{file}") continue with cairo_lang_pie_zip.open(file) as cairo_lang_file, cairo_vm_pie_zip.open(file) as cairo_vm_file: From 70513f0c10d3f9612dc63abb59a409e6c4e57da7 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 18:44:04 -0300 Subject: [PATCH 15/37] Fix pie memory serialization --- vm/src/vm/runners/cairo_pie.rs | 31 +++++++++++-------------------- vm/src/vm/vm_memory/memory.rs | 2 +- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index b8270504bb..d3f4c9ddfa 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -30,7 +30,11 @@ impl From<(isize, usize)> for SegmentInfo { // A simplified version of Memory, without any additional data besides its elements // Contains all addr-value pairs, ordered by index and offset // Allows practical serialization + conversion between CairoPieMemory & Memory -pub type CairoPieMemory = Vec<((usize, usize), MaybeRelocatable)>; +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +pub struct CairoPieMemory( + #[serde(serialize_with = "serde_impl::serialize_memory")] + pub Vec<((usize, usize), MaybeRelocatable)>, +); #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct PublicMemoryPage { @@ -64,7 +68,6 @@ pub enum BuiltinAdditionalData { #[derive(Serialize, Clone, Debug, PartialEq, Eq)] pub struct CairoPie { pub metadata: CairoPieMetadata, - #[serde(serialize_with = "serde_impl::serialize_memory")] pub memory: CairoPieMemory, pub execution_resources: ExecutionResources, pub additional_data: HashMap<String, BuiltinAdditionalData>, @@ -144,8 +147,6 @@ mod serde_impl { utils::CAIRO_PRIME, Felt252, }; - use num_bigint::BigUint; - use num_traits::Num; use serde::{ser::SerializeSeq, Serialize, Serializer}; pub const ADDR_BYTE_LEN: usize = 8; @@ -216,12 +217,12 @@ mod serde_impl { MaybeRelocatable::RelocatableValue(rel_val) => { let mem_addr = ADDR_BASE + *segment as u64 * OFFSET_BASE + *offset as u64; - let reloc_base = BigUint::from_str_radix(RELOCATE_BASE, 16) + let reloc_base = Felt252::from_hex(RELOCATE_BASE) .map_err(|_| serde::ser::Error::custom("invalid relocation base str"))?; let reloc_value = reloc_base - + BigUint::from(rel_val.segment_index as usize) - * BigUint::from(OFFSET_BASE) - + BigUint::from(rel_val.offset); + + Felt252::from(rel_val.segment_index as usize) + * Felt252::from(OFFSET_BASE) + + Felt252::from(rel_val.offset); res.extend_from_slice(mem_addr.to_le_bytes().as_ref()); res.extend_from_slice(reloc_value.to_bytes_le().as_ref()); } @@ -236,12 +237,7 @@ mod serde_impl { }; } - serializer.serialize_str( - res.iter() - .map(|b| format!("{:02x}", b)) - .collect::<String>() - .as_str(), - ) + serializer.serialize_bytes(&res) } pub fn serialize_prime<S>(_value: &(), serializer: S) -> Result<S::Ok, S::Error> @@ -306,11 +302,6 @@ mod test { #[test] fn serialize_cairo_pie_memory() { - #[derive(Serialize)] - struct MemoryWrapper( - #[serde(serialize_with = "serde_impl::serialize_memory")] CairoPieMemory, - ); - let addrs = [ ((1, 0), "0000000000800080"), ((1, 1), "0100000000800080"), @@ -320,7 +311,7 @@ mod test { ((5, 8), "0800000000800280"), ]; - let memory = MemoryWrapper(vec![ + let memory = CairoPieMemory(vec![ (addrs[0].0, MaybeRelocatable::Int(1234.into())), (addrs[1].0, MaybeRelocatable::Int(11.into())), (addrs[2].0, MaybeRelocatable::Int(12.into())), diff --git a/vm/src/vm/vm_memory/memory.rs b/vm/src/vm/vm_memory/memory.rs index 56d6fe0f41..c05c52dffd 100644 --- a/vm/src/vm/vm_memory/memory.rs +++ b/vm/src/vm/vm_memory/memory.rs @@ -524,7 +524,7 @@ impl From<&Memory> for CairoPieMemory { } } } - pie_memory + CairoPieMemory(pie_memory) } } From 08e037eca1c0e4376f748a7bdca10462f19f586f Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 19:46:20 -0300 Subject: [PATCH 16/37] Fix constant value --- vm/src/vm/runners/cairo_pie.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index d3f4c9ddfa..c70958d839 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -154,7 +154,7 @@ mod serde_impl { pub const ADDR_BASE: u64 = 0x8000000000000000; // 2 ** (8 * ADDR_BYTE_LEN - 1) pub const OFFSET_BASE: u64 = 0x800000000000; // 2 ** OFFSET_BIT_LEN pub const RELOCATE_BASE: &str = - "8000000000000000000000000000000000000000000000000000000000000000"; // 2 ** (8 * FIELD_BYTE_LEN - 1) + "57896044618658097711785492504343953926634992332820282019728792003956564819968"; // 2 ** (8 * FIELD_BYTE_LEN - 1) struct Felt252Wrapper<'a>(&'a Felt252); From 39a05bc6da7227ce0f1fcdffb10ae558e2347fc6 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 19:50:43 -0300 Subject: [PATCH 17/37] Save temp changes --- vm/src/tests/cairo_pie_comparator.py | 51 ++++++++++++++++++++++++++++ vm/src/tests/memory_comparator.py | 37 ++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py index ea678a2bc4..826e57e2ae 100755 --- a/vm/src/tests/cairo_pie_comparator.py +++ b/vm/src/tests/cairo_pie_comparator.py @@ -25,3 +25,54 @@ exit(1) print(f"Comparison succesful for {filename1} vs {filename2}") + + # Compare binary files + #Copy paste starts here + + cairo_mem = {} + cairo_rs_mem = {} + + with cairo_lang_pie_zip.open("memory.bin", 'r') as f: + cairo_raw = f.read() + assert len(cairo_raw) % 40 == 0, f'{filename1}: malformed memory file from Cairo VM' + chunks = len(cairo_raw) // 40 + for i in range(0, chunks): + chunk = cairo_raw[i*40:(i+1)*40] + k, v = int.from_bytes(chunk[:8], 'little'), int.from_bytes(chunk[8:], 'little') + assert k not in cairo_mem, f'{filename1}: address {k} has two values' + cairo_mem[k] = v + assert len(cairo_mem) * 40 == len(cairo_raw), f'{filename1}: {len(cairo_mem) * 40} != {len(cairo_raw)}' + + with cairo_vm_pie_zip.open("memory.bin", 'r') as f: + cairo_rs_raw = f.read() + print(len(cairo_rs_raw)) + assert len(cairo_rs_raw) % 40 == 0, f'{filename2}: malformed memory file from cairo-vm' + chunks = len(cairo_rs_raw) // 40 + for i in range(0, chunks): + chunk = cairo_rs_raw[i*40:(i+1)*40] + k, v = int.from_bytes(chunk[:8], 'little'), int.from_bytes(chunk[8:], 'little') + assert k not in cairo_rs_mem, f'{filename2}: address {k} has two values' + cairo_rs_mem[k] = v + assert len(cairo_rs_mem) * 40 == len(cairo_rs_raw), f'{filename2}: {len(cairo_rs_mem) * 40} != {len(cairo_rs_raw)}' + + assert len(cairo_mem) == len(cairo_rs_mem), f'{filename2}: len(cairo_mem)={len(cairo_mem)} len(cairo_mem)={len(cairo_rs_mem)}' + if cairo_mem != cairo_rs_mem: + print(f'Mismatch between {filename1} (Cairo) and {filename2} (cairo_rs)') + print('keys in Cairo but not cairo-vm:') + for k in cairo_mem: + if k in cairo_rs_mem: + continue + print(f'{k}:{v}') + print('keys in cairo_rs but not Cairo:') + for k in cairo_rs_mem: + if k in cairo_mem: + continue + print(f'{k}:{v}') + print('mismatched values (Cairo <-> cairo_rs)):') + for k in cairo_rs_mem: + if k not in cairo_mem: + continue + if cairo_rs_mem[k] == cairo_mem[k]: + continue + print(f'{k}:({cairo_mem[k]} <-> {cairo_rs_mem[k]})') + exit(1) diff --git a/vm/src/tests/memory_comparator.py b/vm/src/tests/memory_comparator.py index c46d4910f3..7f8e95e5cd 100755 --- a/vm/src/tests/memory_comparator.py +++ b/vm/src/tests/memory_comparator.py @@ -52,6 +52,43 @@ def main(): print(f'{k}:({cairo_mem[k]} <-> {cairo_rs_mem[k]})') exit(1) +def compare_memory_file_contents(cairo_raw_mem, cairo_rs_raw_mem): + cairo_mem = read_memory_file_contents(cairo_raw_mem) + cairo_rs_mem = read_memory_file_contents(cairo_rs_raw_mem) + + assert len(cairo_mem) == len(cairo_rs_mem), f'len(cairo_mem)={len(cairo_mem)} len(cairo_mem)={len(cairo_rs_mem)}' + if cairo_mem != cairo_rs_mem: + print(f'Mismatch between cairo_lang and cairo-vm') + print('keys in cairo_lang but not cairo-vm:') + for k in cairo_mem: + if k in cairo_rs_mem: + continue + print(f'{k}:{cairo_mem[k]}') + print('keys in cairo-vm but not cairo_lang:') + for k in cairo_rs_mem: + if k in cairo_mem: + continue + print(f'{k}:{cairo_rs_mem[k]}') + print('mismatched values (cairo_lang <-> cairo-vm)):') + for k in cairo_rs_mem: + if k not in cairo_mem: + continue + if cairo_rs_mem[k] == cairo_mem[k]: + continue + print(f'{k}:({cairo_mem[k]} <-> {cairo_rs_mem[k]})') + exit(1) + +def read_memory_file_contents(raw_mem_content) -> {}: + mem = {} + assert len(raw_mem_content) % 40 == 0, f'Malformed memory file' + chunks = len(raw_mem_content) // 40 + for i in range(0, chunks): + chunk = raw_mem_content[i*40:(i+1)*40] + k, v = int.from_bytes(chunk[:8], 'little'), int.from_bytes(chunk[8:], 'little') + assert k not in mem, f'Address {k} has two values' + mem[k] = v + assert len(mem) * 40 == len(raw_mem_content), f'Malformed memory file' + return mem if __name__ == '__main__': main() From f8699b792c8397484901f03b30f6c971eb28242d Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 19:50:53 -0300 Subject: [PATCH 18/37] Revert "Fix constant value" This reverts commit 08e037eca1c0e4376f748a7bdca10462f19f586f. --- vm/src/vm/runners/cairo_pie.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index c70958d839..d3f4c9ddfa 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -154,7 +154,7 @@ mod serde_impl { pub const ADDR_BASE: u64 = 0x8000000000000000; // 2 ** (8 * ADDR_BYTE_LEN - 1) pub const OFFSET_BASE: u64 = 0x800000000000; // 2 ** OFFSET_BIT_LEN pub const RELOCATE_BASE: &str = - "57896044618658097711785492504343953926634992332820282019728792003956564819968"; // 2 ** (8 * FIELD_BYTE_LEN - 1) + "8000000000000000000000000000000000000000000000000000000000000000"; // 2 ** (8 * FIELD_BYTE_LEN - 1) struct Felt252Wrapper<'a>(&'a Felt252); From 8ae33e169737171a304ca4ee8ab6490d06d5ea65 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Wed, 17 Jan 2024 20:18:25 -0300 Subject: [PATCH 19/37] Use to_bytes instead of serialize impl + simplify scripts --- vm/src/tests/cairo_pie_comparator.py | 48 ++------------------ vm/src/tests/memory_comparator.py | 47 +------------------ vm/src/vm/runners/cairo_pie.rs | 68 +++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 102 deletions(-) diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py index 826e57e2ae..a74c35d1ef 100755 --- a/vm/src/tests/cairo_pie_comparator.py +++ b/vm/src/tests/cairo_pie_comparator.py @@ -3,6 +3,7 @@ import sys import json from zipfile import ZipFile +import memory_comparator filename1 = sys.argv[1] filename2 = sys.argv[2] @@ -27,52 +28,9 @@ print(f"Comparison succesful for {filename1} vs {filename2}") # Compare binary files - #Copy paste starts here cairo_mem = {} cairo_rs_mem = {} - with cairo_lang_pie_zip.open("memory.bin", 'r') as f: - cairo_raw = f.read() - assert len(cairo_raw) % 40 == 0, f'{filename1}: malformed memory file from Cairo VM' - chunks = len(cairo_raw) // 40 - for i in range(0, chunks): - chunk = cairo_raw[i*40:(i+1)*40] - k, v = int.from_bytes(chunk[:8], 'little'), int.from_bytes(chunk[8:], 'little') - assert k not in cairo_mem, f'{filename1}: address {k} has two values' - cairo_mem[k] = v - assert len(cairo_mem) * 40 == len(cairo_raw), f'{filename1}: {len(cairo_mem) * 40} != {len(cairo_raw)}' - - with cairo_vm_pie_zip.open("memory.bin", 'r') as f: - cairo_rs_raw = f.read() - print(len(cairo_rs_raw)) - assert len(cairo_rs_raw) % 40 == 0, f'{filename2}: malformed memory file from cairo-vm' - chunks = len(cairo_rs_raw) // 40 - for i in range(0, chunks): - chunk = cairo_rs_raw[i*40:(i+1)*40] - k, v = int.from_bytes(chunk[:8], 'little'), int.from_bytes(chunk[8:], 'little') - assert k not in cairo_rs_mem, f'{filename2}: address {k} has two values' - cairo_rs_mem[k] = v - assert len(cairo_rs_mem) * 40 == len(cairo_rs_raw), f'{filename2}: {len(cairo_rs_mem) * 40} != {len(cairo_rs_raw)}' - - assert len(cairo_mem) == len(cairo_rs_mem), f'{filename2}: len(cairo_mem)={len(cairo_mem)} len(cairo_mem)={len(cairo_rs_mem)}' - if cairo_mem != cairo_rs_mem: - print(f'Mismatch between {filename1} (Cairo) and {filename2} (cairo_rs)') - print('keys in Cairo but not cairo-vm:') - for k in cairo_mem: - if k in cairo_rs_mem: - continue - print(f'{k}:{v}') - print('keys in cairo_rs but not Cairo:') - for k in cairo_rs_mem: - if k in cairo_mem: - continue - print(f'{k}:{v}') - print('mismatched values (Cairo <-> cairo_rs)):') - for k in cairo_rs_mem: - if k not in cairo_mem: - continue - if cairo_rs_mem[k] == cairo_mem[k]: - continue - print(f'{k}:({cairo_mem[k]} <-> {cairo_rs_mem[k]})') - exit(1) + with cairo_lang_pie_zip.open("memory.bin", 'r') as f1, cairo_vm_pie_zip.open("memory.bin", 'r') as f2: + memory_comparator.compare_memory_file_contents(f1.read(), f2.read()) diff --git a/vm/src/tests/memory_comparator.py b/vm/src/tests/memory_comparator.py index 7f8e95e5cd..686368a4d5 100755 --- a/vm/src/tests/memory_comparator.py +++ b/vm/src/tests/memory_comparator.py @@ -5,52 +5,9 @@ def main(): filename1 = sys.argv[1] filename2 = sys.argv[2] - cairo_mem = {} - cairo_rs_mem = {} - with open(filename1, 'rb') as f: - cairo_raw = f.read() - assert len(cairo_raw) % 40 == 0, f'{filename1}: malformed memory file from Cairo VM' - chunks = len(cairo_raw) // 40 - for i in range(0, chunks): - chunk = cairo_raw[i*40:(i+1)*40] - k, v = int.from_bytes(chunk[:8], 'little'), int.from_bytes(chunk[8:], 'little') - assert k not in cairo_mem, f'{filename1}: address {k} has two values' - cairo_mem[k] = v - assert len(cairo_mem) * 40 == len(cairo_raw), f'{filename1}: {len(cairo_mem) * 40} != {len(cairo_raw)}' - - with open(filename2, 'rb') as f: - cairo_rs_raw = f.read() - assert len(cairo_rs_raw) % 40 == 0, f'{filename2}: malformed memory file from cairo-vm' - chunks = len(cairo_rs_raw) // 40 - for i in range(0, chunks): - chunk = cairo_rs_raw[i*40:(i+1)*40] - k, v = int.from_bytes(chunk[:8], 'little'), int.from_bytes(chunk[8:], 'little') - assert k not in cairo_rs_mem, f'{filename2}: address {k} has two values' - cairo_rs_mem[k] = v - assert len(cairo_rs_mem) * 40 == len(cairo_rs_raw), f'{filename2}: {len(cairo_rs_mem) * 40} != {len(cairo_rs_raw)}' - - assert len(cairo_mem) == len(cairo_rs_mem), f'{filename2}: len(cairo_mem)={len(cairo_mem)} len(cairo_mem)={len(cairo_rs_mem)}' - if cairo_mem != cairo_rs_mem: - print(f'Mismatch between {filename1} (Cairo) and {filename2} (cairo_rs)') - print('keys in Cairo but not cairo-vm:') - for k in cairo_mem: - if k in cairo_rs_mem: - continue - print(f'{k}:{v}') - print('keys in cairo_rs but not Cairo:') - for k in cairo_rs_mem: - if k in cairo_mem: - continue - print(f'{k}:{v}') - print('mismatched values (Cairo <-> cairo_rs)):') - for k in cairo_rs_mem: - if k not in cairo_mem: - continue - if cairo_rs_mem[k] == cairo_mem[k]: - continue - print(f'{k}:({cairo_mem[k]} <-> {cairo_rs_mem[k]})') - exit(1) + with open(filename1, 'rb') as f1, open(filename2, 'rb') as f2: + compare_memory_file_contents(f1.read(), f2.read()) def compare_memory_file_contents(cairo_raw_mem, cairo_rs_raw_mem): cairo_mem = read_memory_file_contents(cairo_raw_mem) diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index d3f4c9ddfa..c763297189 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -120,7 +120,7 @@ impl CairoPie { zip_writer.start_file("metadata.json", options)?; zip_writer.write(serde_json::to_string(&self.metadata).unwrap().as_bytes())?; zip_writer.start_file("memory.bin", options)?; - zip_writer.write(serde_json::to_string(&self.memory).unwrap().as_bytes())?; + zip_writer.write(&self.memory.to_bytes())?; zip_writer.start_file("additional_data.json", options)?; zip_writer.write( serde_json::to_string(&self.additional_data) @@ -139,14 +139,16 @@ impl CairoPie { } mod serde_impl { + use num_traits::Num; use std::collections::HashMap; - use super::CAIRO_PIE_VERSION; + use super::{CAIRO_PIE_VERSION, CairoPieMemory}; use crate::{ types::relocatable::{MaybeRelocatable, Relocatable}, utils::CAIRO_PRIME, Felt252, }; + use num_bigint::BigUint; use serde::{ser::SerializeSeq, Serialize, Serializer}; pub const ADDR_BYTE_LEN: usize = 8; @@ -210,36 +212,78 @@ mod serde_impl { let mut res = Vec::with_capacity(mem_cap); for ((segment, offset), value) in values.iter() { + let mem_addr = ADDR_BASE + *segment as u64 * OFFSET_BASE + *offset as u64; + res.extend_from_slice(mem_addr.to_le_bytes().as_ref()); match value { // Serializes RelocatableValue(little endian): // 1bit | SEGMENT_BITS | OFFSET_BITS // 1 | segment | offset MaybeRelocatable::RelocatableValue(rel_val) => { - let mem_addr = ADDR_BASE + *segment as u64 * OFFSET_BASE + *offset as u64; - - let reloc_base = Felt252::from_hex(RELOCATE_BASE) + let reloc_base = BigUint::from_str_radix(RELOCATE_BASE, 16) .map_err(|_| serde::ser::Error::custom("invalid relocation base str"))?; let reloc_value = reloc_base - + Felt252::from(rel_val.segment_index as usize) - * Felt252::from(OFFSET_BASE) - + Felt252::from(rel_val.offset); - res.extend_from_slice(mem_addr.to_le_bytes().as_ref()); + + BigUint::from(rel_val.segment_index as usize) + * BigUint::from(OFFSET_BASE) + + BigUint::from(rel_val.offset); res.extend_from_slice(reloc_value.to_bytes_le().as_ref()); } // Serializes Int(little endian): // 1bit | Num // 0 | num MaybeRelocatable::Int(data_val) => { - let mem_addr = ADDR_BASE + *segment as u64 * OFFSET_BASE + *offset as u64; - res.extend_from_slice(mem_addr.to_le_bytes().as_ref()); res.extend_from_slice(data_val.to_bytes_le().as_ref()); } }; } - serializer.serialize_bytes(&res) + serializer.serialize_str( + res.iter() + .map(|b| format!("{:02x}", b)) + .collect::<String>() + .as_str(), + ) } + impl CairoPieMemory { + pub fn to_bytes(&self) -> Vec<u8> { + #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] + use alloc::string::String; + #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] + use alloc::vec::Vec; + + // Missing segment and memory holes can be ignored + // as they can be inferred by the address on the prover side + let values = &self.0; + let mem_cap = values.len() * ADDR_BYTE_LEN + values.len() * FIELD_BYTE_LEN; + let mut res = Vec::with_capacity(mem_cap); + + for ((segment, offset), value) in values.iter() { + let mem_addr = ADDR_BASE + *segment as u64 * OFFSET_BASE + *offset as u64; + res.extend_from_slice(mem_addr.to_le_bytes().as_ref()); + match value { + // Serializes RelocatableValue(little endian): + // 1bit | SEGMENT_BITS | OFFSET_BITS + // 1 | segment | offset + MaybeRelocatable::RelocatableValue(rel_val) => { + let reloc_base = BigUint::from_str_radix(RELOCATE_BASE, 16).unwrap(); + let reloc_value = reloc_base + + BigUint::from(rel_val.segment_index as usize) + * BigUint::from(OFFSET_BASE) + + BigUint::from(rel_val.offset); + res.extend_from_slice(reloc_value.to_bytes_le().as_ref()); + } + // Serializes Int(little endian): + // 1bit | Num + // 0 | num + MaybeRelocatable::Int(data_val) => { + res.extend_from_slice(data_val.to_bytes_le().as_ref()); + } + }; + } + res + } +} + pub fn serialize_prime<S>(_value: &(), serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, From 0ac1e33bc4b1a24e2aced9bcd0b99252caf62877 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 10:25:18 -0300 Subject: [PATCH 20/37] Cleanup --- vm/src/tests/cairo_pie_comparator.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py index a74c35d1ef..61dc5d8ed5 100755 --- a/vm/src/tests/cairo_pie_comparator.py +++ b/vm/src/tests/cairo_pie_comparator.py @@ -25,12 +25,8 @@ print(f"Comparison unsuccesful for {filename1}/{file} vs {filename2}/{file}") exit(1) - print(f"Comparison succesful for {filename1} vs {filename2}") - # Compare binary files - - cairo_mem = {} - cairo_rs_mem = {} - with cairo_lang_pie_zip.open("memory.bin", 'r') as f1, cairo_vm_pie_zip.open("memory.bin", 'r') as f2: memory_comparator.compare_memory_file_contents(f1.read(), f2.read()) + + print(f"Comparison succesful for {filename1} vs {filename2}") From 642efa7ab7295f193c9ac41d1c8eec9a344aff6e Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 10:30:39 -0300 Subject: [PATCH 21/37] Fix test --- vm/src/vm/vm_memory/memory.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/src/vm/vm_memory/memory.rs b/vm/src/vm/vm_memory/memory.rs index c05c52dffd..d6d17a2a47 100644 --- a/vm/src/vm/vm_memory/memory.rs +++ b/vm/src/vm/vm_memory/memory.rs @@ -1630,11 +1630,11 @@ mod memory_tests { assert_eq!( CairoPieMemory::from(&memory), - vec![ + CairoPieMemory(vec![ ((1, 2), MaybeRelocatable::from(5)), ((7, 6), MaybeRelocatable::from((1, 2))), ((8, 9), MaybeRelocatable::from(3)) ] - ) + )) } } From 405e8ff09f5e9e7b4725694d787d4c4b2586b942 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 10:45:48 -0300 Subject: [PATCH 22/37] Clean interface + remove unwraps --- cairo-vm-cli/src/main.rs | 5 +- vm/src/vm/runners/cairo_pie.rs | 104 +++++++++++++++------------------ vm/src/vm/vm_memory/memory.rs | 4 +- 3 files changed, 51 insertions(+), 62 deletions(-) diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index a7d8497169..75fad7c893 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -9,7 +9,7 @@ use cairo_vm::vm::errors::trace_errors::TraceError; use cairo_vm::vm::errors::vm_errors::VirtualMachineError; use clap::{CommandFactory, Parser, ValueHint}; use std::io::{self, Write}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use thiserror::Error; #[cfg(feature = "with_mimalloc")] @@ -238,10 +238,11 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { } if let Some(file_name) = args.cairo_pie_output { + let file_path = Path::new(&file_name); cairo_runner .get_cairo_pie(&vm) .map_err(CairoRunError::Runner)? - .write_zip_file(&file_name) + .write_zip_file(&file_path) .unwrap() } diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index c763297189..4c4a17348d 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -105,35 +105,23 @@ pub struct CairoPieVersion { } impl CairoPie { - pub fn serialize_json(&self) -> Result<String, serde_json::Error> { - serde_json::to_string_pretty(&self) - } - - pub fn write_zip_file(&self, file_name: &String) -> Result<(), std::io::Error> { - let path = Path::new(file_name); - let file = File::create(path).unwrap(); + #[cfg(feature = "std")] + pub fn write_zip_file(&self, file_path: &Path) -> Result<(), std::io::Error> { + let file = File::create(file_path)?; let mut zip_writer = ZipWriter::new(file); let options = zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Stored); zip_writer.start_file("version.json", options)?; - zip_writer.write(serde_json::to_string(&self.version).unwrap().as_bytes())?; + zip_writer.write_all(serde_json::to_string(&self.version)?.as_bytes())?; zip_writer.start_file("metadata.json", options)?; - zip_writer.write(serde_json::to_string(&self.metadata).unwrap().as_bytes())?; + zip_writer.write_all(serde_json::to_string(&self.metadata)?.as_bytes())?; zip_writer.start_file("memory.bin", options)?; - zip_writer.write(&self.memory.to_bytes())?; + zip_writer.write_all(&self.memory.to_bytes())?; zip_writer.start_file("additional_data.json", options)?; - zip_writer.write( - serde_json::to_string(&self.additional_data) - .unwrap() - .as_bytes(), - )?; + zip_writer.write_all(serde_json::to_string(&self.additional_data)?.as_bytes())?; zip_writer.start_file("execution_resources.json", options)?; - zip_writer.write( - serde_json::to_string(&self.execution_resources) - .unwrap() - .as_bytes(), - )?; - zip_writer.finish().unwrap(); + zip_writer.write_all(serde_json::to_string(&self.execution_resources)?.as_bytes())?; + zip_writer.finish()?; Ok(()) } } @@ -142,7 +130,7 @@ mod serde_impl { use num_traits::Num; use std::collections::HashMap; - use super::{CAIRO_PIE_VERSION, CairoPieMemory}; + use super::{CairoPieMemory, CAIRO_PIE_VERSION}; use crate::{ types::relocatable::{MaybeRelocatable, Relocatable}, utils::CAIRO_PRIME, @@ -245,44 +233,44 @@ mod serde_impl { } impl CairoPieMemory { - pub fn to_bytes(&self) -> Vec<u8> { - #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] - use alloc::string::String; - #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] - use alloc::vec::Vec; - - // Missing segment and memory holes can be ignored - // as they can be inferred by the address on the prover side - let values = &self.0; - let mem_cap = values.len() * ADDR_BYTE_LEN + values.len() * FIELD_BYTE_LEN; - let mut res = Vec::with_capacity(mem_cap); - - for ((segment, offset), value) in values.iter() { - let mem_addr = ADDR_BASE + *segment as u64 * OFFSET_BASE + *offset as u64; - res.extend_from_slice(mem_addr.to_le_bytes().as_ref()); - match value { - // Serializes RelocatableValue(little endian): - // 1bit | SEGMENT_BITS | OFFSET_BITS - // 1 | segment | offset - MaybeRelocatable::RelocatableValue(rel_val) => { - let reloc_base = BigUint::from_str_radix(RELOCATE_BASE, 16).unwrap(); - let reloc_value = reloc_base - + BigUint::from(rel_val.segment_index as usize) - * BigUint::from(OFFSET_BASE) - + BigUint::from(rel_val.offset); - res.extend_from_slice(reloc_value.to_bytes_le().as_ref()); - } - // Serializes Int(little endian): - // 1bit | Num - // 0 | num - MaybeRelocatable::Int(data_val) => { - res.extend_from_slice(data_val.to_bytes_le().as_ref()); - } - }; + pub fn to_bytes(&self) -> Vec<u8> { + #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] + use alloc::string::String; + #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] + use alloc::vec::Vec; + + // Missing segment and memory holes can be ignored + // as they can be inferred by the address on the prover side + let values = &self.0; + let mem_cap = values.len() * ADDR_BYTE_LEN + values.len() * FIELD_BYTE_LEN; + let mut res = Vec::with_capacity(mem_cap); + + for ((segment, offset), value) in values.iter() { + let mem_addr = ADDR_BASE + *segment as u64 * OFFSET_BASE + *offset as u64; + res.extend_from_slice(mem_addr.to_le_bytes().as_ref()); + match value { + // Serializes RelocatableValue(little endian): + // 1bit | SEGMENT_BITS | OFFSET_BITS + // 1 | segment | offset + MaybeRelocatable::RelocatableValue(rel_val) => { + let reloc_base = BigUint::from_str_radix(RELOCATE_BASE, 16).unwrap(); + let reloc_value = reloc_base + + BigUint::from(rel_val.segment_index as usize) + * BigUint::from(OFFSET_BASE) + + BigUint::from(rel_val.offset); + res.extend_from_slice(reloc_value.to_bytes_le().as_ref()); + } + // Serializes Int(little endian): + // 1bit | Num + // 0 | num + MaybeRelocatable::Int(data_val) => { + res.extend_from_slice(data_val.to_bytes_le().as_ref()); + } + }; + } + res } - res } -} pub fn serialize_prime<S>(_value: &(), serializer: S) -> Result<S::Ok, S::Error> where diff --git a/vm/src/vm/vm_memory/memory.rs b/vm/src/vm/vm_memory/memory.rs index d6d17a2a47..29b36900b0 100644 --- a/vm/src/vm/vm_memory/memory.rs +++ b/vm/src/vm/vm_memory/memory.rs @@ -1634,7 +1634,7 @@ mod memory_tests { ((1, 2), MaybeRelocatable::from(5)), ((7, 6), MaybeRelocatable::from((1, 2))), ((8, 9), MaybeRelocatable::from(3)) - ] - )) + ]) + ) } } From 5f84875d9850f5e5bb01e784d7c1ff65648518d6 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 10:55:02 -0300 Subject: [PATCH 23/37] Fixes --- Makefile | 2 +- cairo-vm-cli/src/main.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 3c60039b59..6afa9e5805 100644 --- a/Makefile +++ b/Makefile @@ -285,7 +285,7 @@ compare_trace_memory: $(CAIRO_RS_TRACE) $(CAIRO_TRACE) $(CAIRO_RS_MEM) $(CAIRO_M cd vm/src/tests; ./compare_vm_state.sh trace memory compare_all_no_proof: $(CAIRO_RS_TRACE) $(CAIRO_TRACE) $(CAIRO_RS_MEM) $(CAIRO_MEM) $(CAIRO_RS_PIE) $(CAIRO_PIE) - cd vm/src/tests; ./compare_vm_state.sh trace memory + cd vm/src/tests; ./compare_vm_state.sh trace memory pie compare_trace: $(CAIRO_RS_TRACE) $(CAIRO_TRACE) cd vm/src/tests; ./compare_vm_state.sh trace diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index 75fad7c893..78911aaa64 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -237,8 +237,8 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { std::fs::write(file_path, json)?; } - if let Some(file_name) = args.cairo_pie_output { - let file_path = Path::new(&file_name); + if let Some(ref file_name) = args.cairo_pie_output { + let file_path = Path::new(file_name); cairo_runner .get_cairo_pie(&vm) .map_err(CairoRunError::Runner)? From cd3dbaf247a3a71c225b21cd4c457959dd0c197a Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 10:55:43 -0300 Subject: [PATCH 24/37] clippy --- cairo-vm-cli/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index 78911aaa64..dd6381376a 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -242,7 +242,7 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { cairo_runner .get_cairo_pie(&vm) .map_err(CairoRunError::Runner)? - .write_zip_file(&file_path) + .write_zip_file(file_path) .unwrap() } From 9b0a7ae1e81cd48f810bf0a7b8efb1207ee7c4a3 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 11:03:24 -0300 Subject: [PATCH 25/37] Move arg validation to a separate func --- cairo-vm-cli/src/main.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index dd6381376a..351121b7df 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -112,9 +112,7 @@ impl FileWriter { } } -fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { - let args = Args::try_parse_from(args)?; - +fn validate_args(args: &Args) -> Result<(), Error> { if args.air_public_input.is_some() && !args.proof_mode { let error = Args::command().error( clap::error::ErrorKind::ArgumentConflict, @@ -155,6 +153,14 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { return Err(Error::Cli(error)); } + Ok(()) +} + +fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { + let args = Args::try_parse_from(args)?; + + validate_args(&args)?; + let trace_enabled = args.trace_file.is_some() || args.air_public_input.is_some(); let mut hint_executor = BuiltinHintProcessor::new_empty(); let cairo_run_config = cairo_run::CairoRunConfig { From 1c2760b9c14bd48315f4aa3ef7bc2de380e58d12 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 11:25:07 -0300 Subject: [PATCH 26/37] Move mutually exclusive argument validation to clap --- cairo-vm-cli/src/main.rs | 59 ++++++---------------------------------- 1 file changed, 9 insertions(+), 50 deletions(-) diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index 351121b7df..e4ad4f10a5 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -7,7 +7,7 @@ use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_def use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; use cairo_vm::vm::errors::trace_errors::TraceError; use cairo_vm::vm::errors::vm_errors::VirtualMachineError; -use clap::{CommandFactory, Parser, ValueHint}; +use clap::{Parser, ValueHint}; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use thiserror::Error; @@ -38,11 +38,16 @@ struct Args { proof_mode: bool, #[structopt(long = "secure_run")] secure_run: Option<bool>, - #[clap(long = "air_public_input")] + #[clap(long = "air_public_input", requires = "proof_mode")] air_public_input: Option<String>, - #[clap(long = "air_private_input")] + #[clap( + long = "air_private_input", + requires = "proof_mode", + requires = "trace_file", + requires = "memory_file" + )] air_private_input: Option<String>, - #[clap(long = "cairo_pie_output")] + #[clap(long = "cairo_pie_output", conflicts_with = "proof_mode")] cairo_pie_output: Option<String>, } @@ -112,55 +117,9 @@ impl FileWriter { } } -fn validate_args(args: &Args) -> Result<(), Error> { - if args.air_public_input.is_some() && !args.proof_mode { - let error = Args::command().error( - clap::error::ErrorKind::ArgumentConflict, - "--air_public_input can only be used in proof_mode.", - ); - return Err(Error::Cli(error)); - } - - if args.air_private_input.is_some() && !args.proof_mode { - let error = Args::command().error( - clap::error::ErrorKind::ArgumentConflict, - "--air_private_input can only be used in proof_mode.", - ); - return Err(Error::Cli(error)); - } - - if args.air_private_input.is_some() && args.trace_file.is_none() { - let error = Args::command().error( - clap::error::ErrorKind::ArgumentConflict, - "--trace_file must be set when --air_private_input is set.", - ); - return Err(Error::Cli(error)); - } - - if args.air_private_input.is_some() && args.memory_file.is_none() { - let error = Args::command().error( - clap::error::ErrorKind::ArgumentConflict, - "--memory_file must be set when --air_private_input is set.", - ); - return Err(Error::Cli(error)); - } - - if args.cairo_pie_output.is_some() && args.proof_mode { - let error = Args::command().error( - clap::error::ErrorKind::ArgumentConflict, - "--proof_mode and --cairo_pie_output cannot be both specified.", - ); - return Err(Error::Cli(error)); - } - - Ok(()) -} - fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { let args = Args::try_parse_from(args)?; - validate_args(&args)?; - let trace_enabled = args.trace_file.is_some() || args.air_public_input.is_some(); let mut hint_executor = BuiltinHintProcessor::new_empty(); let cairo_run_config = cairo_run::CairoRunConfig { From d0a634f3cb4a15d7eb01788224015cbbb8f7b1c7 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 11:29:40 -0300 Subject: [PATCH 27/37] rename var --- vm/src/tests/cairo_pie_comparator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py index 61dc5d8ed5..b4d6629401 100755 --- a/vm/src/tests/cairo_pie_comparator.py +++ b/vm/src/tests/cairo_pie_comparator.py @@ -8,11 +8,11 @@ filename1 = sys.argv[1] filename2 = sys.argv[2] -strict_comparison_files = ["version.json", "metadata.json", "execution_resources.json", "additional_data.json"] +json_files = ["version.json", "metadata.json", "execution_resources.json", "additional_data.json"] with ZipFile(filename1) as cairo_lang_pie_zip, ZipFile(filename2) as cairo_vm_pie_zip: # Compare json files - for file in strict_comparison_files: + for file in json_files: # Skipping this check due to a bug in the memory holes count # TODO: Remove it once the bug is fixed if (filename1 == "../../../cairo_programs/_keccak_alternative_hint.pie.zip" or filename1 == "../../../cairo_programs/relocate_temporary_segment_append.pie.zip" or filename1 == "../../../cairo_programs/keccak_alternative_hint.pie.zip") and file == "execution_resources.json": From 230bf07cd82d693909438afbdca9186d353228c1 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 11:36:39 -0300 Subject: [PATCH 28/37] Add Chaneglog entry --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64620c5850..1cd3d5ef81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ #### Upcoming Changes +* feat: Add `cairo_pie_output` flag to `cairo_vm_cli` [#1578] (https://github.com/lambdaclass/cairo-vm/pull/1578) + * Fix serialization of CairoPie to be fully compatible with the python version + * Add `CairoPie::write_zip_file` + * Move handling of required and exclusive arguments in `cairo-vm-cli` to struct definition using clap derives + * feat: Add `air_private_input` flag to `cairo1-run` [#1559] (https://github.com/lambdaclass/cairo-vm/pull/1559) * feat: Add `args` flag to `cairo1-run` [#15551] (https://github.com/lambdaclass/cairo-vm/pull/15551) From f4c7a96daf23577685fb357d3b381ddc9d304984 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 11:38:28 -0300 Subject: [PATCH 29/37] Make zip dep optional --- vm/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vm/Cargo.toml b/vm/Cargo.toml index a7af63173d..6c33144a20 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -19,6 +19,7 @@ std = [ "starknet-crypto/std", "dep:num-prime", "thiserror-no-std/std", + "dep:zip", ] cairo-1-hints = [ "dep:cairo-lang-starknet", @@ -42,7 +43,7 @@ extensive_hints = [] print = ["std"] [dependencies] -zip = "0.6.6" +zip = {version = "0.6.6", optional = true } mimalloc = { workspace = true, optional = true } num-bigint = { workspace = true } rand = { workspace = true } From 333e6f8f0df949c82ccaea98d71ce9fa1da2bde5 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 11:59:31 -0300 Subject: [PATCH 30/37] Fix wasm imports --- vm/src/vm/runners/cairo_pie.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index 4c4a17348d..a768893d02 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -1,6 +1,5 @@ -use std::{fs::File, io::Write, path::Path}; - use super::cairo_runner::ExecutionResources; +use crate::stdlib::prelude::{String, Vec}; use crate::{ serde::deserialize_program::BuiltinName, stdlib::{collections::HashMap, prelude::*}, @@ -8,7 +7,11 @@ use crate::{ Felt252, }; use serde::{Deserialize, Serialize}; -use zip::ZipWriter; +#[cfg(feature = "std")] +use { + std::{fs::File, io::Write, path::Path}, + zip::ZipWriter, +}; const CAIRO_PIE_VERSION: &str = "1.1"; @@ -127,10 +130,11 @@ impl CairoPie { } mod serde_impl { + use crate::stdlib::collections::HashMap; use num_traits::Num; - use std::collections::HashMap; use super::{CairoPieMemory, CAIRO_PIE_VERSION}; + use crate::stdlib::prelude::{String, Vec}; use crate::{ types::relocatable::{MaybeRelocatable, Relocatable}, utils::CAIRO_PRIME, @@ -189,11 +193,6 @@ mod serde_impl { where S: Serializer, { - #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] - use alloc::string::String; - #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] - use alloc::vec::Vec; - // Missing segment and memory holes can be ignored // as they can be inferred by the address on the prover side let mem_cap = values.len() * ADDR_BYTE_LEN + values.len() * FIELD_BYTE_LEN; @@ -234,11 +233,6 @@ mod serde_impl { impl CairoPieMemory { pub fn to_bytes(&self) -> Vec<u8> { - #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] - use alloc::string::String; - #[cfg(any(target_arch = "wasm32", no_std, not(feature = "std")))] - use alloc::vec::Vec; - // Missing segment and memory holes can be ignored // as they can be inferred by the address on the prover side let values = &self.0; From 8ad3c66cc025a637084e0413461255fd8ffea968 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 12:11:30 -0300 Subject: [PATCH 31/37] Add file extension --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6afa9e5805..239508e029 100644 --- a/Makefile +++ b/Makefile @@ -100,7 +100,7 @@ $(TEST_DIR)/%.rs.trace $(TEST_DIR)/%.rs.memory $(TEST_DIR)/%.rs.pie.zip: $(TEST_ cargo llvm-cov run -p cairo-vm-cli --release --no-report -- --layout all_cairo $< --trace_file $(@D)/$(*F) --memory_file $(@D)/$(*F).rs.memory --cairo_pie_output $(@D)/$(*F).rs.pie.zip $(TEST_DIR)/%.trace $(TEST_DIR)/%.memory $(TEST_DIR)/%.pie.zip: $(TEST_DIR)/%.json - cairo-run --layout starknet_with_keccak --program $< --trace_file $(@D)/$(*F) --memory_file $(@D)/$(*F).memory --cairo_pie_output $(@D)/$(*F).pie.zip + cairo-run --layout starknet_with_keccak --program $< --trace_file $(@D)/$(*F).trace --memory_file $(@D)/$(*F).memory --cairo_pie_output $(@D)/$(*F).pie.zip $(NORETROCOMPAT_DIR)/%.json: $(NORETROCOMPAT_DIR)/%.cairo cairo-compile --cairo_path="$(TEST_DIR):$(BENCH_DIR):$(NORETROCOMPAT_DIR)" $< --output $@ From 03426ba346697fa9d98db662055ef39094f6023e Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 12:43:48 -0300 Subject: [PATCH 32/37] Add file extension --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 239508e029..1da8c57d2d 100644 --- a/Makefile +++ b/Makefile @@ -97,7 +97,7 @@ $(TEST_DIR)/%.json: $(TEST_DIR)/%.cairo cairo-compile --cairo_path="$(TEST_DIR):$(BENCH_DIR)" $< --output $@ $(TEST_DIR)/%.rs.trace $(TEST_DIR)/%.rs.memory $(TEST_DIR)/%.rs.pie.zip: $(TEST_DIR)/%.json $(RELBIN) - cargo llvm-cov run -p cairo-vm-cli --release --no-report -- --layout all_cairo $< --trace_file $(@D)/$(*F) --memory_file $(@D)/$(*F).rs.memory --cairo_pie_output $(@D)/$(*F).rs.pie.zip + cargo llvm-cov run -p cairo-vm-cli --release --no-report -- --layout all_cairo $< --trace_file $(@D)/$(*F).rs.trace --memory_file $(@D)/$(*F).rs.memory --cairo_pie_output $(@D)/$(*F).rs.pie.zip $(TEST_DIR)/%.trace $(TEST_DIR)/%.memory $(TEST_DIR)/%.pie.zip: $(TEST_DIR)/%.json cairo-run --layout starknet_with_keccak --program $< --trace_file $(@D)/$(*F).trace --memory_file $(@D)/$(*F).memory --cairo_pie_output $(@D)/$(*F).pie.zip From 0a130f730aacb9f75caa699eb8d55bef7c2f15ee Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 14:04:39 -0300 Subject: [PATCH 33/37] Remove unwrap + improve coverage --- cairo-vm-cli/src/main.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index e4ad4f10a5..328be606aa 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -207,8 +207,7 @@ fn run(args: impl Iterator<Item = String>) -> Result<(), Error> { cairo_runner .get_cairo_pie(&vm) .map_err(CairoRunError::Runner)? - .write_zip_file(file_path) - .unwrap() + .write_zip_file(file_path)? } Ok(()) @@ -291,6 +290,7 @@ mod tests { #[values(false, true)] entrypoint: bool, #[values(false, true)] air_public_input: bool, #[values(false, true)] air_private_input: bool, + #[values(false, true)] cairo_pie_output: bool, ) { let mut args = vec!["cairo-vm-cli".to_string()]; if let Some(layout) = layout { @@ -302,6 +302,9 @@ mod tests { if air_private_input { args.extend_from_slice(&["--air_private_input".to_string(), "/dev/null".to_string()]); } + if cairo_pie_output { + args.extend_from_slice(&["--cairo_pie_output".to_string(), "/dev/null".to_string()]); + } if proof_mode { trace_file = true; args.extend_from_slice(&["--proof_mode".to_string()]); @@ -325,6 +328,7 @@ mod tests { args.push("../cairo_programs/proof_programs/fibonacci.json".to_string()); if air_public_input && !proof_mode || (air_private_input && (!proof_mode || !trace_file || !memory_file)) + || cairo_pie_output && proof_mode { assert_matches!(run(args.into_iter()), Err(_)); } else { From 4ca5964429fdf0198e434a963f7e6d049d37c5f9 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 15:35:57 -0300 Subject: [PATCH 34/37] quick fix --- cairo-vm-cli/src/main.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index 328be606aa..4deab7b8be 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -47,7 +47,13 @@ struct Args { requires = "memory_file" )] air_private_input: Option<String>, - #[clap(long = "cairo_pie_output", conflicts_with = "proof_mode")] + #[clap( + long = "cairo_pie_output", + conflicts_with = "proof_mode", + // We need to add these two or else passing cairo_pie_output + either of these without proof_mode will fail + conflicts_with = "air_private_input", + conflicts_with = "air_public_input", + )] cairo_pie_output: Option<String>, } From 2cce1a678a070374dfef9376ff9014b8c804b1b7 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 15:42:22 -0300 Subject: [PATCH 35/37] Clean solution --- cairo-vm-cli/src/main.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index 4deab7b8be..a3c349d79a 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -42,17 +42,14 @@ struct Args { air_public_input: Option<String>, #[clap( long = "air_private_input", - requires = "proof_mode", - requires = "trace_file", - requires = "memory_file" + requires_all = ["proof_mode", "trace_file", "memory_file"] )] air_private_input: Option<String>, #[clap( long = "cairo_pie_output", - conflicts_with = "proof_mode", - // We need to add these two or else passing cairo_pie_output + either of these without proof_mode will fail - conflicts_with = "air_private_input", - conflicts_with = "air_public_input", + // We need to add these air_private_input & air_public_input or else + // passing cairo_pie_output + either of these without proof_mode will not fail + conflicts_with_all = ["proof_mode", "air_private_input", "air_public_input"] )] cairo_pie_output: Option<String>, } From 3ab3d3089dc2f56d406c25284781463ca4442158 Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Thu, 18 Jan 2024 15:46:56 -0300 Subject: [PATCH 36/37] Update README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1e45ad3f50..1d7d274d46 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,8 @@ The cairo-vm-cli supports the following optional arguments: - `--air_private_input <AIR_PRIVATE_INPUT>`: Receives the name of a file and outputs the AIR private inputs into it. Can only be used if proof_mode, trace_file & memory_file are also enabled. +- `--cairo_pie_output <CAIRO_PIE_OUTPUT>`: Receives the name of a file and outputs the Cairo PIE into it. Can only be used if proof_mode, is not enabled. + For example, to obtain the air public inputs from a fibonacci program run, we can run : ```bash From e539c1397a5913713ab44fdf2a60be251a2296eb Mon Sep 17 00:00:00 2001 From: Federica <fedemoletta@hotmail.com> Date: Fri, 19 Jan 2024 15:07:09 -0300 Subject: [PATCH 37/37] Update makefile targets --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index bef40b55dc..c1f433574a 100644 --- a/Makefile +++ b/Makefile @@ -234,11 +234,11 @@ cairo_bench_programs: $(COMPILED_BENCHES) cairo_1_test_contracts: $(CAIRO_1_COMPILED_CASM_CONTRACTS) cairo_2_test_contracts: $(CAIRO_2_COMPILED_CASM_CONTRACTS) -cairo_proof_trace: $(CAIRO_TRACE_PROOF) $(CAIRO_MEM_PROOF) $(CAIRO_AIR_PUBLIC_INPUT) -cairo-vm_proof_trace: $(CAIRO_RS_TRACE_PROOF) $(CAIRO_RS_MEM_PROOF) $(CAIRO_RS_AIR_PUBLIC_INPUT) +cairo_proof_trace: $(CAIRO_TRACE_PROOF) $(CAIRO_MEM_PROOF) $(CAIRO_AIR_PUBLIC_INPUT) $(CAIRO_AIR_PRIVATE_INPUT) +cairo-vm_proof_trace: $(CAIRO_RS_TRACE_PROOF) $(CAIRO_RS_MEM_PROOF) $(CAIRO_RS_AIR_PUBLIC_INPUT) $(CAIRO_RS_AIR_PRIVATE_INPUT) -cairo_trace: $(CAIRO_TRACE) $(CAIRO_MEM) -cairo-vm_trace: $(CAIRO_RS_TRACE) $(CAIRO_RS_MEM) +cairo_trace: $(CAIRO_TRACE) $(CAIRO_MEM) $(CAIRO_PIE) +cairo-vm_trace: $(CAIRO_RS_TRACE) $(CAIRO_RS_MEM) $(CAIRO_RS_PIE) test: cairo_proof_programs cairo_test_programs cairo_1_test_contracts cairo_2_test_contracts cargo llvm-cov nextest --no-report --workspace --features "test_utils, cairo-1-hints"