diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 3329fef4b9..a6a7a38f43 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -323,6 +323,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- @@ -365,7 +366,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 @@ -402,6 +403,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 }} @@ -502,6 +504,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 @@ -513,6 +516,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 @@ -522,9 +526,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/CHANGELOG.md b/CHANGELOG.md index c1b0b4daa2..3e6afa22c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ * refactor: remove static lifetime for name str parameter requirement for constant getter +* feat: Add `cairo_pie_output` flag to `cairo1-run` [#1581] (https://github.com/lambdaclass/cairo-vm/pull/1581) + +* 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 doc + default impl for ResourceTracker trait [#1576] (https://github.com/lambdaclass/cairo-vm/pull/1576) * feat: Add `air_private_input` flag to `cairo1-run` [#1559] (https://github.com/lambdaclass/cairo-vm/pull/1559) 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/Makefile b/Makefile index 06c7f41050..18c7774bc9 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 \ @@ -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 $(@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)/%.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 $(@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 $@ @@ -232,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_COMMAND:=cargo nextest run ifdef TEST_COLLECT_COVERAGE @@ -287,6 +289,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 pie + compare_trace: $(CAIRO_RS_TRACE) $(CAIRO_TRACE) cd vm/src/tests; ./compare_vm_state.sh trace @@ -311,6 +316,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 @@ -319,6 +327,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/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 `: 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 `: 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 diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index a24ef7bb92..a3c349d79a 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -7,9 +7,9 @@ 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::PathBuf; +use std::path::{Path, PathBuf}; use thiserror::Error; #[cfg(feature = "with_mimalloc")] @@ -38,10 +38,20 @@ struct Args { proof_mode: bool, #[structopt(long = "secure_run")] secure_run: Option, - #[clap(long = "air_public_input")] + #[clap(long = "air_public_input", requires = "proof_mode")] air_public_input: Option, - #[clap(long = "air_private_input")] + #[clap( + long = "air_private_input", + requires_all = ["proof_mode", "trace_file", "memory_file"] + )] air_private_input: Option, + #[clap( + long = "cairo_pie_output", + // 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, } fn validate_layout(value: &str) -> Result { @@ -113,38 +123,6 @@ impl FileWriter { fn run(args: impl Iterator) -> Result<(), Error> { let args = Args::try_parse_from(args)?; - 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)); - } - 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 +205,14 @@ fn run(args: impl Iterator) -> Result<(), Error> { std::fs::write(file_path, json)?; } + 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)? + .write_zip_file(file_path)? + } + Ok(()) } @@ -307,6 +293,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 { @@ -318,6 +305,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()]); @@ -341,6 +331,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 { diff --git a/cairo1-run/README.md b/cairo1-run/README.md index d96b38bfac..2f0cc5a8b3 100644 --- a/cairo1-run/README.md +++ b/cairo1-run/README.md @@ -64,3 +64,5 @@ The cairo1-run cli supports the following optional arguments: * `--air_public_input `: Receives the name of a file and outputs the AIR public inputs into it. Can only be used if proof_mode is also enabled. * `--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 `: Receives the name of a file and outputs the Cairo PIE into it. Can only be used if proof_mode, is not enabled. diff --git a/cairo1-run/src/main.rs b/cairo1-run/src/main.rs index 86e8f69b5b..ce063df076 100644 --- a/cairo1-run/src/main.rs +++ b/cairo1-run/src/main.rs @@ -85,10 +85,20 @@ struct Args { layout: String, #[clap(long = "proof_mode", value_parser)] proof_mode: bool, - #[clap(long = "air_public_input", value_parser)] + #[clap(long = "air_public_input", requires = "proof_mode")] air_public_input: Option, - #[clap(long = "air_private_input", value_parser)] + #[clap( + long = "air_private_input", + requires_all = ["proof_mode", "trace_file", "memory_file"] + )] air_private_input: Option, + #[clap( + long = "cairo_pie_output", + // 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, // Arguments should be spaced, with array elements placed between brackets // For example " --args '1 2 [1 2 3]'" will yield 3 arguments, with the last one being an array of 3 elements #[clap(long = "args", default_value = "", value_parser=process_args)] @@ -238,37 +248,6 @@ impl FileWriter { fn run(args: impl Iterator) -> Result, Error> { let args = Args::try_parse_from(args)?; - 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)); - } let compiler_config = CompilerConfig { replace_ids: true, @@ -442,7 +421,7 @@ fn run(args: impl Iterator) -> Result, Erro } // Set stop pointers for builtins so we can obtain the air public input - if args.air_public_input.is_some() { + if args.air_public_input.is_some() || args.cairo_pie_output.is_some() { // Cairo 1 programs have other return values aside from the used builtin's final pointers, so we need to hand-pick them let ret_types_sizes = main_func .signature @@ -484,7 +463,9 @@ fn run(args: impl Iterator) -> Result, Erro vm.builtins_final_stack_from_stack_pointer_dict(&builtin_name_to_stack_pointer)?; // Build execution public memory - runner.finalize_segments(&mut vm)?; + if args.proof_mode { + runner.finalize_segments(&mut vm)?; + } } runner.relocate(&mut vm, true)?; @@ -521,6 +502,10 @@ fn run(args: impl Iterator) -> Result, Erro std::fs::write(file_path, json)?; } + if let Some(ref file_path) = args.cairo_pie_output { + runner.get_cairo_pie(&vm)?.write_zip_file(file_path)? + } + if let Some(trace_path) = args.trace_file { let relocated_trace = runner .relocated_trace @@ -904,7 +889,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/fibonacci.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/fibonacci.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/fibonacci.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_fibonacci_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -912,7 +897,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/factorial.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/factorial.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/factorial.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_factorial_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -920,7 +905,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/array_get.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/array_get.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/array_get.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_array_get_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -928,7 +913,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/enum_flow.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/enum_flow.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/enum_flow.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_enum_flow_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -936,7 +921,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/enum_match.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/enum_match.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/enum_match.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_enum_match_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -944,7 +929,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/hello.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/hello.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/hello.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_hello_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -952,7 +937,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/ops.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/ops.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/ops.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_ops_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -960,7 +945,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/print.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/print.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/print.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_print_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -968,7 +953,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/recursion.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/recursion.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/recursion.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_recursion_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -976,7 +961,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/sample.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/sample.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/sample.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_sample_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -984,7 +969,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/poseidon.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/poseidon.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/poseidon.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_poseidon_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -992,7 +977,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/poseidon_pedersen.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/poseidon_pedersen.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/poseidon_pedersen.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_poseidon_pedersen_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -1000,7 +985,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/pedersen_example.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/pedersen_example.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/pedersen_example.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_pedersen_example_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -1008,7 +993,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/simple.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/simple.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/simple.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_simple_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -1016,7 +1001,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/simple_struct.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/simple_struct.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/simple_struct.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_simple_struct_ok(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -1024,7 +1009,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/dictionaries.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/dictionaries.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/dictionaries.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null"].as_slice())] fn test_run_dictionaries(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -1032,7 +1017,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/branching.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--args", "0"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/branching.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null", "--args", "0"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/branching.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null", "--args", "0"].as_slice())] fn test_run_branching_0(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -1040,7 +1025,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/branching.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--args", "17"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/branching.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null", "--args", "17"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/branching.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null", "--args", "96"].as_slice())] fn test_run_branching_not_0(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -1048,7 +1033,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/branching.cairo", "--layout", "all_cairo"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/branching.cairo", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/branching.cairo", "--layout", "all_cairo", "--proof_mode"].as_slice())] fn test_run_branching_no_args(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -1064,7 +1049,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/array_input_sum.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--args", "2 [1 2 3 4] 0 [9 8]"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/array_input_sum.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null", "--args", "2 [1 2 3 4] 0 [9 8]"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/array_input_sum.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null", "--args", "2 [1 2 3 4] 0 [9 8]"].as_slice())] fn test_array_input_sum(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); @@ -1072,7 +1057,7 @@ mod tests { } #[rstest] - #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/tensor.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--args", "[2 2] [1 2 3 4]"].as_slice())] + #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/tensor.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--cairo_pie_output", "/dev/null", "--args", "[2 2] [1 2 3 4]"].as_slice())] #[case(["cairo1-run", "../cairo_programs/cairo-1-programs/with_input/tensor.cairo", "--trace_file", "/dev/null", "--memory_file", "/dev/null", "--layout", "all_cairo", "--proof_mode", "--air_public_input", "/dev/null", "--air_private_input", "/dev/null", "--args", "[2 2] [1 2 3 4]"].as_slice())] fn test_tensor(#[case] args: &[&str]) { let args = args.iter().cloned().map(String::from); diff --git a/cairo_programs/_keccak.cairo b/cairo_programs/keccak.cairo similarity index 100% rename from cairo_programs/_keccak.cairo rename to cairo_programs/keccak.cairo diff --git a/cairo_programs/_keccak_alternative_hint.cairo b/cairo_programs/keccak_alternative_hint.cairo similarity index 100% rename from cairo_programs/_keccak_alternative_hint.cairo rename to cairo_programs/keccak_alternative_hint.cairo diff --git a/cairo_programs/proof_programs/_keccak.cairo b/cairo_programs/proof_programs/_keccak.cairo deleted file mode 120000 index 73c4dc9243..0000000000 --- a/cairo_programs/proof_programs/_keccak.cairo +++ /dev/null @@ -1 +0,0 @@ -../_keccak.cairo \ No newline at end of file diff --git a/cairo_programs/proof_programs/_keccak_alternative_hint.cairo b/cairo_programs/proof_programs/_keccak_alternative_hint.cairo deleted file mode 120000 index 188837a642..0000000000 --- a/cairo_programs/proof_programs/_keccak_alternative_hint.cairo +++ /dev/null @@ -1 +0,0 @@ -../_keccak_alternative_hint.cairo \ No newline at end of file diff --git a/cairo_programs/proof_programs/keccak.cairo b/cairo_programs/proof_programs/keccak.cairo new file mode 120000 index 0000000000..85e66e5a21 --- /dev/null +++ b/cairo_programs/proof_programs/keccak.cairo @@ -0,0 +1 @@ +../keccak.cairo \ No newline at end of file diff --git a/cairo_programs/proof_programs/keccak_alternative_hint.cairo b/cairo_programs/proof_programs/keccak_alternative_hint.cairo new file mode 120000 index 0000000000..6960b2186f --- /dev/null +++ b/cairo_programs/proof_programs/keccak_alternative_hint.cairo @@ -0,0 +1 @@ +../keccak_alternative_hint.cairo \ No newline at end of file diff --git a/vm/Cargo.toml b/vm/Cargo.toml index e7f9fe029a..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,6 +43,7 @@ extensive_hints = [] print = ["std"] [dependencies] +zip = {version = "0.6.6", optional = true } mimalloc = { workspace = true, optional = true } num-bigint = { workspace = true } rand = { workspace = true } diff --git a/vm/src/serde/serialize_program.rs b/vm/src/serde/serialize_program.rs index 32550d187c..e50ba1c872 100644 --- a/vm/src/serde/serialize_program.rs +++ b/vm/src/serde/serialize_program.rs @@ -250,14 +250,14 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn program_json_from_program_test() { let programs_bytes: Vec> = [ - include_bytes!("../../../cairo_programs/_keccak.json").to_vec(), + include_bytes!("../../../cairo_programs/keccak.json").to_vec(), include_bytes!("../../../cairo_programs/assert_nn.json").to_vec(), include_bytes!("../../../cairo_programs/bitwise_recursion.json").to_vec(), include_bytes!("../../../cairo_programs/blake2s_felts.json").to_vec(), include_bytes!("../../../cairo_programs/cairo_finalize_keccak_block_size_1000.json") .to_vec(), include_bytes!("../../../cairo_programs/bitwise_recursion.json").to_vec(), - include_bytes!("../../../cairo_programs/_keccak.json").to_vec(), + include_bytes!("../../../cairo_programs/keccak.json").to_vec(), include_bytes!("../../../cairo_programs/ec_double_slope.json").to_vec(), include_bytes!("../../../cairo_programs/example_blake2s.json").to_vec(), include_bytes!("../../../cairo_programs/fibonacci.json").to_vec(), @@ -291,14 +291,14 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn serialize_and_deserialize_programs() { let programs_bytes: Vec> = [ - include_bytes!("../../../cairo_programs/_keccak.json").to_vec(), + include_bytes!("../../../cairo_programs/keccak.json").to_vec(), include_bytes!("../../../cairo_programs/assert_nn.json").to_vec(), include_bytes!("../../../cairo_programs/bitwise_recursion.json").to_vec(), include_bytes!("../../../cairo_programs/blake2s_felts.json").to_vec(), include_bytes!("../../../cairo_programs/cairo_finalize_keccak_block_size_1000.json") .to_vec(), include_bytes!("../../../cairo_programs/bitwise_recursion.json").to_vec(), - include_bytes!("../../../cairo_programs/_keccak.json").to_vec(), + include_bytes!("../../../cairo_programs/keccak.json").to_vec(), include_bytes!("../../../cairo_programs/ec_double_slope.json").to_vec(), include_bytes!("../../../cairo_programs/example_blake2s.json").to_vec(), include_bytes!("../../../cairo_programs/fibonacci.json").to_vec(), diff --git a/vm/src/tests/cairo_pie_comparator.py b/vm/src/tests/cairo_pie_comparator.py new file mode 100755 index 0000000000..b4d6629401 --- /dev/null +++ b/vm/src/tests/cairo_pie_comparator.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import sys +import json +from zipfile import ZipFile +import memory_comparator + +filename1 = sys.argv[1] +filename2 = sys.argv[2] + +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 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": + 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) + cv_content = json.load(cairo_vm_file) + if cl_content != cv_content: + print(f"Comparison unsuccesful for {filename1}/{file} vs {filename2}/{file}") + exit(1) + + # Compare binary files + 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}") diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index f291a678af..c06a3d4e3a 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -462,7 +462,7 @@ fn keccak_add_uint256() { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn keccak() { - let program_data = include_bytes!("../../../cairo_programs/_keccak.json"); + let program_data = include_bytes!("../../../cairo_programs/keccak.json"); run_program_simple(program_data.as_slice()); } @@ -732,7 +732,7 @@ fn mul_s_inv() { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn keccak_alternative_hint() { - let program_data = include_bytes!("../../../cairo_programs/_keccak_alternative_hint.json"); + let program_data = include_bytes!("../../../cairo_programs/keccak_alternative_hint.json"); run_program_simple(program_data.as_slice()); } 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 diff --git a/vm/src/tests/memory_comparator.py b/vm/src/tests/memory_comparator.py index c46d4910f3..686368a4d5 100755 --- a/vm/src/tests/memory_comparator.py +++ b/vm/src/tests/memory_comparator.py @@ -5,45 +5,28 @@ 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)}' + with open(filename1, 'rb') as f1, open(filename2, 'rb') as f2: + compare_memory_file_contents(f1.read(), f2.read()) - assert len(cairo_mem) == len(cairo_rs_mem), f'{filename2}: len(cairo_mem)={len(cairo_mem)} len(cairo_mem)={len(cairo_rs_mem)}' +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 {filename1} (Cairo) and {filename2} (cairo_rs)') - print('keys in Cairo but not cairo-vm:') + 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}:{v}') - print('keys in cairo_rs but not Cairo:') + 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}:{v}') - print('mismatched values (Cairo <-> cairo_rs)):') + 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 @@ -52,6 +35,17 @@ def main(): 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() diff --git a/vm/src/vm/runners/builtin_runner/keccak.rs b/vm/src/vm/runners/builtin_runner/keccak.rs index 3eed4a61b6..244efa866d 100644 --- a/vm/src/vm/runners/builtin_runner/keccak.rs +++ b/vm/src/vm/runners/builtin_runner/keccak.rs @@ -412,7 +412,7 @@ mod tests { vm.segments.segment_used_sizes = Some(vec![0]); let program = Program::from_bytes( - include_bytes!("../../../../../cairo_programs/_keccak.json"), + include_bytes!("../../../../../cairo_programs/keccak.json"), Some("main"), ) .unwrap(); diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index d464065899..a768893d02 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -1,4 +1,5 @@ use super::cairo_runner::ExecutionResources; +use crate::stdlib::prelude::{String, Vec}; use crate::{ serde::deserialize_program::BuiltinName, stdlib::{collections::HashMap, prelude::*}, @@ -6,6 +7,11 @@ use crate::{ Felt252, }; use serde::{Deserialize, Serialize}; +#[cfg(feature = "std")] +use { + std::{fs::File, io::Write, path::Path}, + zip::ZipWriter, +}; const CAIRO_PIE_VERSION: &str = "1.1"; @@ -27,7 +33,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 { @@ -49,9 +59,11 @@ 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), Output(OutputBuiltinAdditionalData), // Signatures are composed of (r, s) tuples + #[serde(serialize_with = "serde_impl::serialize_signature_additional_data")] Signature(HashMap), None, } @@ -59,7 +71,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, @@ -96,11 +107,40 @@ pub struct CairoPieVersion { pub cairo_pie: (), } +impl CairoPie { + #[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_all(serde_json::to_string(&self.version)?.as_bytes())?; + zip_writer.start_file("metadata.json", options)?; + zip_writer.write_all(serde_json::to_string(&self.metadata)?.as_bytes())?; + zip_writer.start_file("memory.bin", options)?; + zip_writer.write_all(&self.memory.to_bytes())?; + zip_writer.start_file("additional_data.json", options)?; + zip_writer.write_all(serde_json::to_string(&self.additional_data)?.as_bytes())?; + zip_writer.start_file("execution_resources.json", options)?; + zip_writer.write_all(serde_json::to_string(&self.execution_resources)?.as_bytes())?; + zip_writer.finish()?; + Ok(()) + } +} + mod serde_impl { - use super::CAIRO_PIE_VERSION; - use crate::{types::relocatable::MaybeRelocatable, utils::CAIRO_PRIME, Felt252}; - use num_bigint::BigUint; + use crate::stdlib::collections::HashMap; use num_traits::Num; + + use super::{CairoPieMemory, CAIRO_PIE_VERSION}; + use crate::stdlib::prelude::{String, Vec}; + 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; @@ -153,39 +193,31 @@ 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; 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 = BigUint::from_str_radix(RELOCATE_BASE, 16) .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); - res.extend_from_slice(mem_addr.to_le_bytes().as_ref()); 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()); } }; @@ -199,6 +231,41 @@ mod serde_impl { ) } + impl CairoPieMemory { + pub fn to_bytes(&self) -> 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(_value: &(), serializer: S) -> Result where S: Serializer, @@ -216,6 +283,43 @@ mod serde_impl { { serializer.serialize_str(CAIRO_PIE_VERSION) } + + pub fn serialize_signature_additional_data( + values: &HashMap, + serializer: S, + ) -> Result + where + S: Serializer, + { + let mut seq_serializer = serializer.serialize_seq(Some(values.len()))?; + + for (key, (x, y)) in values { + seq_serializer.serialize_element(&[ + [ + Felt252Wrapper(&Felt252::from(key.segment_index)), + Felt252Wrapper(&Felt252::from(key.offset)), + ], + [Felt252Wrapper(x), Felt252Wrapper(y)], + ])?; + } + seq_serializer.end() + } + + pub fn serialize_hash_additional_data( + values: &[Relocatable], + serializer: S, + ) -> Result + where + S: Serializer, + { + 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.end() + } } #[cfg(test)] @@ -224,11 +328,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"), @@ -238,7 +337,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..29b36900b0 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) } } @@ -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)) - ] + ]) ) } }