From 14ec3e33cb33287cf3a012b852af9932364b0bf5 Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Fri, 27 Sep 2024 19:17:37 -0300 Subject: [PATCH 01/34] Add dynamic layout basic support (#1824) * Fix Zero segment location. * Fixed has_zero_segment naming * Fix prover input. * Fixed version reading when no version is supplied * Added change to changelog. * fix test_from_serializable() * fix panic_impl error * fix cairo version * Add dummy changelog * Pin wasm-bindgen * Register change in CHANGELOG * Update Cargo.lock * Remove changes from CHANGELOG * Add argument parsing for layout params file * Add dynamic support (no implement) * Add cairo_layout_params_file.example.json * Implement dynamic layout creation * Update CHANGELOG * Add cli dynamic support for cairo 1 * Make wasm compatible * Use public_memory_fraction = 4 vy default * Deserialize bool from int * Add comparison with python-vm (failing) * Rebuild .rs files in makefile * Use 8 as dynamic public_memory_fraction The same value is used in python-vm * Use None ratio for dynamic unused builtins * Add rangecheck96 to private inputs * Make dyn py files depend on params_file * Use cpu_component_step=1 by default * Fix typo in private inputs * Add range check value to air private input test * Fix zero segment location * Use zero builtin instead of None * Add debug scripts * Remove dup makefile recipes * remove outdated test * Enable ensure-no_std on test * Fix tests * Add correct test * Rename tset * Add comment * Add debugging document * Update cairo layout params file * Remove duplicated range check * Remove dup * Remove debugging and scrippts (moveed to another branch) * Add comment * Add tests * Add dynamic test to cairo-vm-cli * Add parse test * Remove compare all dynamic * Add script for comparing with dynamic layouts * Add tests to workflow * Delete logic changes They are going to be moved to another branch * Delete more logic changes * Update rust.yml * Rename compare_outputs_dynamic_layout.sh to compare_outputs_dynamic_layouts.sh * Update test script * Add more tests * Rename parameter for clarity * Enable mod builtin only on feature with dynamic layout * Remove debug assert * Refactor errors into variants * Fix failing test * Move cairo_layout_params_file to test folder * Document cairo_layout_param_file in the README.md * Fix clippy warning * Use mod_builtin feature in tests --------- Co-authored-by: Alon Titelman Co-authored-by: Yuval Goldberg Co-authored-by: Omri Eshhar --- .github/workflows/rust.yml | 39 ++ .gitignore | 1 + CHANGELOG.md | 5 + README.md | 2 + bench/criterion_benchmark.rs | 12 +- bench/iai_benchmark.rs | 10 +- cairo-vm-cli/src/main.rs | 25 ++ cairo1-run/src/cairo_run.rs | 7 +- cairo1-run/src/main.rs | 25 ++ fuzzer/Cargo.lock | 2 +- vm/src/cairo_run.rs | 12 +- vm/src/tests/cairo_layout_params_file.json | 29 ++ vm/src/tests/cairo_run_test.rs | 1 + .../tests/compare_outputs_dynamic_layouts.sh | 164 +++++++++ vm/src/tests/mod.rs | 2 + .../builtins_instance_def.rs | 84 +++-- vm/src/types/layout.rs | 335 +++++++++++++++++- vm/src/types/layout_name.rs | 2 +- vm/src/utils.rs | 9 +- vm/src/vm/errors/runner_errors.rs | 4 + vm/src/vm/runners/builtin_runner/modulo.rs | 3 +- vm/src/vm/runners/cairo_runner.rs | 29 +- 22 files changed, 744 insertions(+), 58 deletions(-) create mode 100644 vm/src/tests/cairo_layout_params_file.json create mode 100755 vm/src/tests/compare_outputs_dynamic_layouts.sh diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0efa960359..6dde21ab95 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -725,6 +725,45 @@ jobs: - name: Run script run: ./vm/src/tests/compare_factorial_outputs_all_layouts.sh + compare-outputs-dynamic-layouts: + name: Compare outputs with dynamic layouts + needs: [ build-programs, build-release ] + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Python3 Build + uses: actions/setup-python@v4 + with: + python-version: '3.9' + cache: 'pip' + + - name: Install cairo-lang and deps + run: pip install -r requirements.txt + + - name: Fetch release binary + uses: actions/cache/restore@v3 + with: + key: cli-bin-rel-${{ github.sha }} + path: target/release/cairo-vm-cli + fail-on-cache-miss: true + + - uses: actions/download-artifact@master + with: + name: proof_programs + path: cairo_programs/proof_programs/ + + - name: Fetch programs + uses: actions/cache/restore@v3 + with: + path: ${{ env.CAIRO_PROGRAMS_PATH }} + key: cairo_proof_programs-cache-${{ hashFiles('cairo_programs/**/*.cairo', 'examples/wasm-demo/src/array_sum.cairo') }} + fail-on-cache-miss: true + + - name: Run script + run: ./vm/src/tests/compare_outputs_dynamic_layouts.sh + compare-run-from-cairo-pie-all-outputs: name: Compare all outputs from running Cairo PIEs needs: [ build-programs, build-release, run-cairo-release ] diff --git a/.gitignore b/.gitignore index 69a905dfdf..69fa82e403 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,5 @@ cairo-vm-cli/air_input.pub ensure-no_std/Cargo.lock cairo_programs/proof_programs/*.cairo +!cairo_layout_params_file.json !vm/src/tests/cairo_pie_test_output.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 03c22eb7fd..3317000d50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ #### Upcoming Changes +* feat(BREAKING): [#1824](https://github.com/lambdaclass/cairo-vm/pull/1824): + * Add support for dynamic layout + * CLI change(BREAKING): The flag `cairo_layout_params_file` must be specified when using dynamic layout. + * Signature change(BREAKING): Both `CairoRunner::new` and `CairoRunner::new_v2` now receive an `Option`, used only with dynamic layout. + * chore: bump pip `cairo-lang` 0.13.2 [#1827](https://github.com/lambdaclass/cairo-vm/pull/1827) * chore: bump `cairo-lang-` dependencies to 2.8.0 [#1833](https://github.com/lambdaclass/cairo-vm/pull/1833/files) diff --git a/README.md b/README.md index 0618a0fcea..a7ecf920dc 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,8 @@ The cairo-vm-cli supports the following optional arguments: - `run_from_cairo_pie`: Runs a Cairo PIE instead of a compiled json file. The name of the file will be the first argument received by the CLI (as if it were to run a normal compiled program). Can only be used if proof_mode is not enabled. +- `cairo_layout_params_file`: Only used with dynamic layout. Receives the name of a json file with the dynamic layout parameters. + For example, to obtain the air public inputs from a fibonacci program run, we can run : ```bash diff --git a/bench/criterion_benchmark.rs b/bench/criterion_benchmark.rs index 7078ad21a8..d473fe61f6 100644 --- a/bench/criterion_benchmark.rs +++ b/bench/criterion_benchmark.rs @@ -30,6 +30,7 @@ fn build_many_runners(c: &mut Criterion) { CairoRunner::new( black_box(&program), black_box(LayoutName::starknet_with_keccak), + black_box(None), black_box(false), black_box(false), ) @@ -45,7 +46,16 @@ fn load_program_data(c: &mut Criterion) { let program = Program::from_bytes(program.as_slice(), Some("main")).unwrap(); c.bench_function("initialize", |b| { b.iter_batched( - || CairoRunner::new(&program, LayoutName::starknet_with_keccak, false, false).unwrap(), + || { + CairoRunner::new( + &program, + LayoutName::starknet_with_keccak, + None, + false, + false, + ) + .unwrap() + }, |mut runner| _ = black_box(runner.initialize(false).unwrap()), BatchSize::SmallInput, ) diff --git a/bench/iai_benchmark.rs b/bench/iai_benchmark.rs index b5bff69dce..441f79b5bc 100644 --- a/bench/iai_benchmark.rs +++ b/bench/iai_benchmark.rs @@ -34,6 +34,7 @@ fn build_runner() { let runner = CairoRunner::new( black_box(&program), LayoutName::starknet_with_keccak, + None, false, false, ) @@ -47,7 +48,14 @@ fn build_runner_helper() -> CairoRunner { //Picked the biggest one at the time of writing let program = include_bytes!("../cairo_programs/benchmarks/keccak_integration_benchmark.json"); let program = Program::from_bytes(program.as_slice(), Some("main")).unwrap(); - CairoRunner::new(&program, LayoutName::starknet_with_keccak, false, false).unwrap() + CairoRunner::new( + &program, + LayoutName::starknet_with_keccak, + None, + false, + false, + ) + .unwrap() } #[inline(never)] diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index 08095128ca..51cb3a649a 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -6,6 +6,7 @@ use cairo_vm::cairo_run::{self, EncodeTraceError}; use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; #[cfg(feature = "with_tracer")] use cairo_vm::serde::deserialize_program::DebugInfo; +use cairo_vm::types::layout::CairoLayoutParams; use cairo_vm::types::layout_name::LayoutName; use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; use cairo_vm::vm::errors::trace_errors::TraceError; @@ -43,8 +44,13 @@ struct Args { entrypoint: String, #[structopt(long = "memory_file")] memory_file: Option, + /// When using dynamic layout, it's parameters must be specified through a layout params file. #[clap(long = "layout", default_value = "plain", value_enum)] layout: LayoutName, + /// Required when using with dynamic layout. + /// Ignored otherwise. + #[clap(long = "cairo_layout_params_file", required_if_eq("layout", "dynamic"))] + cairo_layout_params_file: Option, #[structopt(long = "proof_mode")] proof_mode: bool, #[structopt(long = "secure_run")] @@ -162,6 +168,11 @@ fn run(args: impl Iterator) -> Result<(), Error> { let trace_enabled = args.trace_file.is_some() || args.air_public_input.is_some(); + let cairo_layout_params = match args.cairo_layout_params_file { + Some(file) => Some(CairoLayoutParams::from_file(&file)?), + None => None, + }; + let cairo_run_config = cairo_run::CairoRunConfig { entrypoint: &args.entrypoint, trace_enabled, @@ -170,6 +181,7 @@ fn run(args: impl Iterator) -> Result<(), Error> { proof_mode: args.proof_mode, secure_run: args.secure_run, allow_missing_builtins: args.allow_missing_builtins, + dynamic_layout_params: cairo_layout_params, ..Default::default() }; @@ -405,6 +417,19 @@ mod tests { assert_matches!(run(args), Err(Error::Runner(_))); } + #[test] + fn test_run_dynamic_params() { + let mut args = vec!["cairo-vm-cli".to_string()]; + args.extend_from_slice(&["--layout".to_string(), "dynamic".to_string()]); + args.extend_from_slice(&[ + "--cairo_layout_params_file".to_string(), + "../vm/src/tests/cairo_layout_params_file.json".to_string(), + ]); + args.push("../cairo_programs/proof_programs/fibonacci.json".to_string()); + + assert_matches!(run(args.into_iter()), Ok(_)); + } + //Since the functionality here is trivial, I just call the function //to fool Codecov. #[test] diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index 3f8095e160..bf654e9724 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -38,8 +38,8 @@ use cairo_vm::{ math_utils::signed_felt, serde::deserialize_program::{ApTracking, FlowTrackingData, HintParams, ReferenceManager}, types::{ - builtin_name::BuiltinName, layout_name::LayoutName, program::Program, - relocatable::MaybeRelocatable, + builtin_name::BuiltinName, layout::CairoLayoutParams, layout_name::LayoutName, + program::Program, relocatable::MaybeRelocatable, }, vm::{ errors::{runner_errors::RunnerError, vm_errors::VirtualMachineError}, @@ -86,6 +86,7 @@ pub struct Cairo1RunConfig<'a> { pub relocate_mem: bool, /// Cairo layout chosen for the run pub layout: LayoutName, + pub dynamic_layout_params: Option, /// Run in proof_mode pub proof_mode: bool, /// Should be true if either air_public_input or cairo_pie_output are needed @@ -106,6 +107,7 @@ impl Default for Cairo1RunConfig<'_> { proof_mode: false, finalize_builtins: false, append_return_values: false, + dynamic_layout_params: None, } } } @@ -248,6 +250,7 @@ pub fn cairo_run_program( let mut runner = CairoRunner::new_v2( &program, cairo_run_config.layout, + cairo_run_config.dynamic_layout_params.clone(), runner_mode, cairo_run_config.trace_enabled, )?; diff --git a/cairo1-run/src/main.rs b/cairo1-run/src/main.rs index 47c9abfbca..edad364df1 100644 --- a/cairo1-run/src/main.rs +++ b/cairo1-run/src/main.rs @@ -4,6 +4,7 @@ use cairo1_run::{cairo_run_program, Cairo1RunConfig, FuncArg}; use cairo_lang_compiler::{ compile_prepared_db, db::RootDatabase, project::setup_project, CompilerConfig, }; +use cairo_vm::types::layout::CairoLayoutParams; use cairo_vm::{ air_public_input::PublicInputError, types::layout_name::LayoutName, vm::errors::trace_errors::TraceError, Felt252, @@ -24,8 +25,13 @@ struct Args { trace_file: Option, #[structopt(long = "memory_file")] memory_file: Option, + /// When using dynamic layout, it's parameters must be specified through a layout params file. #[clap(long = "layout", default_value = "plain", value_enum)] layout: LayoutName, + /// Required when using with dynamic layout. + /// Ignored otherwise. + #[clap(long = "cairo_layout_params_file", required_if_eq("layout", "dynamic"))] + cairo_layout_params_file: Option, #[clap(long = "proof_mode", value_parser)] proof_mode: bool, #[clap(long = "air_public_input", requires = "proof_mode")] @@ -153,6 +159,11 @@ fn run(args: impl Iterator) -> Result, Error> { args.args = process_args(&std::fs::read_to_string(filename)?).unwrap(); } + let cairo_layout_params = match args.cairo_layout_params_file { + Some(file) => Some(CairoLayoutParams::from_file(&file)?), + None => None, + }; + let cairo_run_config = Cairo1RunConfig { proof_mode: args.proof_mode, serialize_output: args.print_output, @@ -162,6 +173,7 @@ fn run(args: impl Iterator) -> Result, Error> { args: &args.args.0, finalize_builtins: args.air_public_input.is_some() || args.cairo_pie_output.is_some(), append_return_values: args.append_return_values, + dynamic_layout_params: cairo_layout_params, }; // Try to parse the file as a sierra program @@ -478,6 +490,19 @@ mod tests { assert_matches!(run(args), Ok(Some(res)) if res == expected_output, "Program {} failed with flags {}", program, extra_flags.concat()); } + #[test] + fn test_run_dynamic_params() { + let mut args = vec!["cairo1-run".to_string()]; + args.extend_from_slice(&["--layout".to_string(), "dynamic".to_string()]); + args.extend_from_slice(&[ + "--cairo_layout_params_file".to_string(), + "../vm/src/tests/cairo_layout_params_file.json".to_string(), + ]); + args.push("../cairo_programs/cairo-1-programs/fibonacci.cairo".to_string()); + + assert_matches!(run(args.into_iter()), Ok(_)); + } + // these tests are separated so as to run them without --append_return_values and --proof_mode options // since they require to use the squashed version of felt252 #[rstest] diff --git a/fuzzer/Cargo.lock b/fuzzer/Cargo.lock index e1ccedbfb8..e1ef312c3a 100644 --- a/fuzzer/Cargo.lock +++ b/fuzzer/Cargo.lock @@ -216,7 +216,7 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "1.0.0-rc5" +version = "1.0.1" dependencies = [ "anyhow", "arbitrary", diff --git a/vm/src/cairo_run.rs b/vm/src/cairo_run.rs index de2540fb2e..0e61856a3b 100644 --- a/vm/src/cairo_run.rs +++ b/vm/src/cairo_run.rs @@ -1,6 +1,9 @@ use crate::{ hint_processor::hint_processor_definition::HintProcessor, - types::{builtin_name::BuiltinName, layout_name::LayoutName, program::Program}, + types::{ + builtin_name::BuiltinName, layout::CairoLayoutParams, layout_name::LayoutName, + program::Program, + }, vm::{ errors::{ cairo_run_errors::CairoRunError, runner_errors::RunnerError, vm_exception::VmException, @@ -26,6 +29,9 @@ pub struct CairoRunConfig<'a> { pub trace_enabled: bool, pub relocate_mem: bool, pub layout: LayoutName, + /// The `dynamic_layout_params` argument should only be used with dynamic layout. + /// It is ignored otherwise. + pub dynamic_layout_params: Option, pub proof_mode: bool, pub secure_run: Option, pub disable_trace_padding: bool, @@ -43,6 +49,7 @@ impl<'a> Default for CairoRunConfig<'a> { secure_run: None, disable_trace_padding: false, allow_missing_builtins: None, + dynamic_layout_params: None, } } } @@ -65,6 +72,7 @@ pub fn cairo_run_program_with_initial_scope( let mut cairo_runner = CairoRunner::new( program, cairo_run_config.layout, + cairo_run_config.dynamic_layout_params.clone(), cairo_run_config.proof_mode, cairo_run_config.trace_enabled, )?; @@ -151,6 +159,7 @@ pub fn cairo_run_pie( let mut cairo_runner = CairoRunner::new( &program, cairo_run_config.layout, + cairo_run_config.dynamic_layout_params.clone(), false, cairo_run_config.trace_enabled, )?; @@ -223,6 +232,7 @@ pub fn cairo_run_fuzzed_program( let mut cairo_runner = CairoRunner::new( &program, cairo_run_config.layout, + cairo_run_config.dynamic_layout_params.clone(), cairo_run_config.proof_mode, cairo_run_config.trace_enabled, )?; diff --git a/vm/src/tests/cairo_layout_params_file.json b/vm/src/tests/cairo_layout_params_file.json new file mode 100644 index 0000000000..f4d0d736f5 --- /dev/null +++ b/vm/src/tests/cairo_layout_params_file.json @@ -0,0 +1,29 @@ +{ + "rc_units": 4, + "log_diluted_units_per_step": 4, + "cpu_component_step": 8, + "memory_units_per_step": 8, + "uses_pedersen_builtin": true, + "pedersen_ratio": 256, + "uses_range_check_builtin": true, + "range_check_ratio": 8, + "uses_ecdsa_builtin": true, + "ecdsa_ratio": 2048, + "uses_bitwise_builtin": true, + "bitwise_ratio": 16, + "uses_ec_op_builtin": true, + "ec_op_ratio": 1024, + "uses_keccak_builtin": true, + "keccak_ratio": 2048, + "uses_poseidon_builtin": true, + "poseidon_ratio": 256, + "uses_range_check96_builtin": true, + "range_check96_ratio": 8, + "range_check96_ratio_den": 1, + "uses_add_mod_builtin": true, + "add_mod_ratio": 128, + "add_mod_ratio_den": 1, + "uses_mul_mod_builtin": true, + "mul_mod_ratio": 256, + "mul_mod_ratio_den": 1 +} diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index ce42ca31dd..55126c98df 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -1182,6 +1182,7 @@ fn run_program_with_custom_mod_builtin_params( let mut cairo_runner = CairoRunner::new( &program, cairo_run_config.layout, + cairo_run_config.dynamic_layout_params, cairo_run_config.proof_mode, cairo_run_config.trace_enabled, ) diff --git a/vm/src/tests/compare_outputs_dynamic_layouts.sh b/vm/src/tests/compare_outputs_dynamic_layouts.sh new file mode 100755 index 0000000000..7077edaa44 --- /dev/null +++ b/vm/src/tests/compare_outputs_dynamic_layouts.sh @@ -0,0 +1,164 @@ +#!/usr/bin/env bash +# +# Compares programs with different dynamic layouts against cairo-lang + + +# Build temporary dynamic layout params files +TEMP_FOLDER=$(mktemp -d) +cat < "$TEMP_FOLDER/all_cairo.json" +{ + "rc_units": 4, + "log_diluted_units_per_step": 4, + "cpu_component_step": 8, + "memory_units_per_step": 8, + "uses_pedersen_builtin": true, + "pedersen_ratio": 256, + "uses_range_check_builtin": true, + "range_check_ratio": 8, + "uses_ecdsa_builtin": true, + "ecdsa_ratio": 2048, + "uses_bitwise_builtin": true, + "bitwise_ratio": 16, + "uses_ec_op_builtin": true, + "ec_op_ratio": 1024, + "uses_keccak_builtin": true, + "keccak_ratio": 2048, + "uses_poseidon_builtin": true, + "poseidon_ratio": 256, + "uses_range_check96_builtin": true, + "range_check96_ratio": 8, + "range_check96_ratio_den": 1, + "uses_add_mod_builtin": true, + "add_mod_ratio": 128, + "add_mod_ratio_den": 1, + "uses_mul_mod_builtin": true, + "mul_mod_ratio": 256, + "mul_mod_ratio_den": 1 +} +EOF +cat < "$TEMP_FOLDER/double_all_cairo.json" +{ + "rc_units": 8, + "log_diluted_units_per_step": 8, + "cpu_component_step": 16, + "memory_units_per_step": 16, + "uses_pedersen_builtin": true, + "pedersen_ratio": 512, + "uses_range_check_builtin": true, + "range_check_ratio": 16, + "uses_ecdsa_builtin": true, + "ecdsa_ratio": 4096, + "uses_bitwise_builtin": true, + "bitwise_ratio": 32, + "uses_ec_op_builtin": true, + "ec_op_ratio": 2048, + "uses_keccak_builtin": true, + "keccak_ratio": 4096, + "uses_poseidon_builtin": true, + "poseidon_ratio": 512, + "uses_range_check96_builtin": true, + "range_check96_ratio": 16, + "range_check96_ratio_den": 1, + "uses_add_mod_builtin": true, + "add_mod_ratio": 256, + "add_mod_ratio_den": 1, + "uses_mul_mod_builtin": true, + "mul_mod_ratio": 512, + "mul_mod_ratio_den": 1 +} +EOF + +# Build cases to execute +CASES=( + "cairo_programs/proof_programs/factorial.json;all_cairo" + "cairo_programs/proof_programs/factorial.json;double_all_cairo" + "cairo_programs/proof_programs/fibonacci.json;all_cairo" + "cairo_programs/proof_programs/fibonacci.json;double_all_cairo" + "cairo_programs/proof_programs/bigint.json;all_cairo" + "cairo_programs/proof_programs/bigint.json;double_all_cairo" + "cairo_programs/proof_programs/dict.json;all_cairo" + "cairo_programs/proof_programs/dict.json;double_all_cairo" + "cairo_programs/proof_programs/sha256.json;all_cairo" + "cairo_programs/proof_programs/sha256.json;double_all_cairo" + "cairo_programs/proof_programs/keccak.json;all_cairo" + "cairo_programs/proof_programs/keccak.json;double_all_cairo" +) + +passed_tests=0 +failed_tests=0 +exit_code=0 + +for case in "${CASES[@]}"; do + IFS=";" read -r program layout <<< "$case" + + full_program="$program" + full_layout="$TEMP_FOLDER/$layout.json" + + # Run cairo-vm + echo "Running cairo-vm with case: $case" + cargo run -p cairo-vm-cli --features mod_builtin --release -- "$full_program" \ + --layout "dynamic" --cairo_layout_params_file "$full_layout" --proof_mode \ + --trace_file program_rs.trace --memory_file program_rs.memory --air_public_input program_rs.air_public_input --air_private_input program_rs.air_private_input + + # Run cairo-lang + echo "Running cairo-lang with case: $case" + cairo-run --program "$full_program" \ + --layout "dynamic" --cairo_layout_params_file "$full_layout" --proof_mode \ + --trace_file program_py.trace --memory_file program_py.memory --air_public_input program_py.air_public_input --air_private_input program_py.air_private_input + + # Compare trace + echo "Running trace comparison for case: $case" + if ! diff -q program_rs.trace program_py.trace; then + echo "Trace differs for case: $case" + exit_code=1 + failed_tests=$((failed_tests + 1)) + else + passed_tests=$((passed_tests + 1)) + fi + + # Compare memory + echo "Running memory comparison for case: $case" + if ! ./vm/src/tests/memory_comparator.py program_rs.memory program_py.memory; then + echo "Memory differs for case: $case" + exit_code=1 + failed_tests=$((failed_tests + 1)) + else + passed_tests=$((passed_tests + 1)) + fi + + # Compare air public input + echo "Running air public input comparison for case: $case" + if ! ./vm/src/tests/air_public_input_comparator.py program_rs.air_public_input program_py.air_public_input; then + echo "Air public input differs for case: $case" + exit_code=1 + failed_tests=$((failed_tests + 1)) + else + passed_tests=$((passed_tests + 1)) + fi + + # Compare air private input + echo "Running air private input comparison for case: $case" + if ! ./vm/src/tests/air_private_input_comparator.py program_rs.air_private_input program_py.air_private_input; then + echo "Air private input differs for case: $case" + exit_code=1 + failed_tests=$((failed_tests + 1)) + else + passed_tests=$((passed_tests + 1)) + fi + + # Clean files generated by the script + echo "Cleaning files" + rm program_rs.* + rm program_py.* +done + +if test $failed_tests != 0; then + echo "Comparisons: $failed_tests failed, $passed_tests passed, $((failed_tests + passed_tests)) total" +elif test $passed_tests = 0; then + echo "No tests ran!" + exit_code=2 +else + echo "All $passed_tests tests passed; no discrepancies found" +fi + +exit "${exit_code}" diff --git a/vm/src/tests/mod.rs b/vm/src/tests/mod.rs index 6df6e743fe..9141c3a0f9 100644 --- a/vm/src/tests/mod.rs +++ b/vm/src/tests/mod.rs @@ -113,6 +113,7 @@ fn run_cairo_1_entrypoint( let mut runner = CairoRunner::new( &(contract_class.clone().try_into().unwrap()), LayoutName::all_cairo, + None, false, false, ) @@ -217,6 +218,7 @@ fn run_cairo_1_entrypoint_with_run_resources( let mut runner = CairoRunner::new( &(contract_class.clone().try_into().unwrap()), LayoutName::all_cairo, + None, false, false, ) diff --git a/vm/src/types/instance_definitions/builtins_instance_def.rs b/vm/src/types/instance_definitions/builtins_instance_def.rs index ab13cf14fb..cf7d420636 100644 --- a/vm/src/types/instance_definitions/builtins_instance_def.rs +++ b/vm/src/types/instance_definitions/builtins_instance_def.rs @@ -1,3 +1,5 @@ +use crate::types::layout::CairoLayoutParams; + use super::mod_instance_def::ModInstanceDef; use super::{ bitwise_instance_def::BitwiseInstanceDef, ec_op_instance_def::EcOpInstanceDef, @@ -192,25 +194,60 @@ impl BuiltinsInstanceDef { } } - pub(crate) fn dynamic() -> BuiltinsInstanceDef { + pub(crate) fn dynamic(params: CairoLayoutParams) -> BuiltinsInstanceDef { + let pedersen = Some(PedersenInstanceDef { + ratio: Some(params.pedersen_ratio), + }); + let range_check = Some(RangeCheckInstanceDef { + ratio: Some(params.range_check_ratio), + }); + let ecdsa = Some(EcdsaInstanceDef { + ratio: Some(params.ecdsa_ratio), + }); + let bitwise = Some(BitwiseInstanceDef { + ratio: Some(params.bitwise_ratio), + }); + let ec_op = Some(EcOpInstanceDef { + ratio: Some(params.ec_op_ratio), + }); + let keccak = Some(KeccakInstanceDef { + ratio: Some(params.keccak_ratio), + }); + let poseidon = Some(PoseidonInstanceDef { + ratio: Some(params.poseidon_ratio), + }); + let range_check96 = Some(RangeCheckInstanceDef { + ratio: Some(params.range_check96_ratio), + }); + #[cfg(feature = "mod_builtin")] + let add_mod = Some(ModInstanceDef { + ratio: Some(params.add_mod_ratio), + word_bit_len: 96, + batch_size: 1, + }); + #[cfg(feature = "mod_builtin")] + let mul_mod = Some(ModInstanceDef { + ratio: Some(params.mul_mod_ratio), + word_bit_len: 96, + batch_size: 1, + }); + #[cfg(not(feature = "mod_builtin"))] + let add_mod = None; + #[cfg(not(feature = "mod_builtin"))] + let mul_mod = None; + BuiltinsInstanceDef { output: true, - pedersen: Some(PedersenInstanceDef::new(None)), - range_check: Some(RangeCheckInstanceDef::new(None)), - ecdsa: Some(EcdsaInstanceDef::new(None)), - bitwise: Some(BitwiseInstanceDef::new(None)), - ec_op: Some(EcOpInstanceDef::new(None)), - keccak: None, - poseidon: None, - range_check96: None, - #[cfg(feature = "mod_builtin")] - add_mod: Some(ModInstanceDef::new(None, 1, 96)), - #[cfg(feature = "mod_builtin")] - mul_mod: Some(ModInstanceDef::new(None, 1, 96)), - #[cfg(not(feature = "mod_builtin"))] - add_mod: None, - #[cfg(not(feature = "mod_builtin"))] - mul_mod: None, + pedersen, + range_check, + ecdsa, + bitwise, + ec_op, + keccak, + poseidon, + range_check96, + add_mod, + mul_mod, } } } @@ -342,17 +379,4 @@ mod tests { assert!(builtins.keccak.is_none()); assert!(builtins.poseidon.is_none()); } - - #[test] - fn get_builtins_dynamic() { - let builtins = BuiltinsInstanceDef::dynamic(); - assert!(builtins.output); - assert!(builtins.pedersen.is_some()); - assert!(builtins.range_check.is_some()); - assert!(builtins.ecdsa.is_some()); - assert!(builtins.bitwise.is_some()); - assert!(builtins.ec_op.is_some()); - assert!(builtins.keccak.is_none()); - assert!(builtins.poseidon.is_none()); - } } diff --git a/vm/src/types/layout.rs b/vm/src/types/layout.rs index ee0fae3196..b1f52e7698 100644 --- a/vm/src/types/layout.rs +++ b/vm/src/types/layout.rs @@ -1,12 +1,16 @@ -use crate::types::layout_name::LayoutName; +use crate::{types::layout_name::LayoutName, vm::errors::runner_errors::RunnerError}; -use super::instance_definitions::{ - builtins_instance_def::BuiltinsInstanceDef, diluted_pool_instance_def::DilutedPoolInstanceDef, +use super::{ + builtin_name::BuiltinName, + instance_definitions::{ + builtins_instance_def::BuiltinsInstanceDef, + diluted_pool_instance_def::DilutedPoolInstanceDef, + }, }; pub(crate) const MEMORY_UNITS_PER_STEP: u32 = 8; -use serde::Serialize; +use serde::{Deserialize, Deserializer, Serialize}; #[derive(Serialize, Debug)] pub struct CairoLayout { @@ -117,20 +121,208 @@ impl CairoLayout { } } - pub(crate) fn dynamic_instance() -> CairoLayout { + pub(crate) fn dynamic_instance(params: CairoLayoutParams) -> CairoLayout { CairoLayout { name: LayoutName::dynamic, - rc_units: 16, - builtins: BuiltinsInstanceDef::dynamic(), + rc_units: params.rc_units, public_memory_fraction: 8, - diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()), + diluted_pool_instance_def: Some(DilutedPoolInstanceDef { + units_per_step: 2_u32.pow(params.log_diluted_units_per_step), + ..DilutedPoolInstanceDef::default() + }), + builtins: BuiltinsInstanceDef::dynamic(params), + } + } +} + +#[cfg(feature = "test_utils")] +use arbitrary::{self, Arbitrary}; + +#[cfg_attr(feature = "test_utils", derive(Arbitrary))] +#[derive(Deserialize, Debug, Clone, Default)] +#[serde(try_from = "RawCairoLayoutParams")] +pub struct CairoLayoutParams { + pub rc_units: u32, + pub log_diluted_units_per_step: u32, + pub pedersen_ratio: u32, + pub range_check_ratio: u32, + pub ecdsa_ratio: u32, + pub bitwise_ratio: u32, + pub ec_op_ratio: u32, + pub keccak_ratio: u32, + pub poseidon_ratio: u32, + pub range_check96_ratio: u32, + pub add_mod_ratio: u32, + pub mul_mod_ratio: u32, + // the following are not used right now + pub cpu_component_step: u32, + pub memory_units_per_step: u32, + pub range_check96_ratio_den: u32, + pub mul_mod_ratio_den: u32, + pub add_mod_ratio_den: u32, +} + +impl CairoLayoutParams { + #[cfg(feature = "std")] + pub fn from_file(params_path: &std::path::Path) -> std::io::Result { + let params_file = std::fs::File::open(params_path)?; + let params = serde_json::from_reader(params_file)?; + Ok(params) + } +} + +// The CairoLayoutParams contains aditional constraints that can't be validated by serde alone. +// To work around this. we use an aditional structure `RawCairoLayoutParams` that gets deserialized by serde +// and then its tranformed into `CairoLayoutParams`. + +#[derive(Deserialize, Debug, Default, Clone)] +pub struct RawCairoLayoutParams { + pub rc_units: u32, + pub log_diluted_units_per_step: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_pedersen_builtin: bool, + pub pedersen_ratio: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_range_check_builtin: bool, + pub range_check_ratio: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_ecdsa_builtin: bool, + pub ecdsa_ratio: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_bitwise_builtin: bool, + pub bitwise_ratio: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_ec_op_builtin: bool, + pub ec_op_ratio: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_keccak_builtin: bool, + pub keccak_ratio: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_poseidon_builtin: bool, + pub poseidon_ratio: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_range_check96_builtin: bool, + pub range_check96_ratio: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_add_mod_builtin: bool, + pub add_mod_ratio: u32, + #[serde(deserialize_with = "bool_from_int_or_bool")] + pub uses_mul_mod_builtin: bool, + pub mul_mod_ratio: u32, + // the following are not used right now + pub cpu_component_step: u32, + pub memory_units_per_step: u32, + pub range_check96_ratio_den: u32, + pub mul_mod_ratio_den: u32, + pub add_mod_ratio_den: u32, +} + +impl TryFrom for CairoLayoutParams { + type Error = RunnerError; + + fn try_from(value: RawCairoLayoutParams) -> Result { + if !value.uses_pedersen_builtin && value.pedersen_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::pedersen, + )); + } + if !value.uses_range_check_builtin && value.range_check_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::range_check, + )); + } + if !value.uses_ecdsa_builtin && value.ecdsa_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::ecdsa, + )); + } + if !value.uses_bitwise_builtin && value.bitwise_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::bitwise, + )); + } + if !value.uses_ec_op_builtin && value.ec_op_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::ec_op, + )); + } + if !value.uses_keccak_builtin && value.keccak_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::keccak, + )); + } + if !value.uses_poseidon_builtin && value.poseidon_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::poseidon, + )); + } + if !value.uses_range_check96_builtin && value.range_check96_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::range_check96, + )); } + if !value.uses_add_mod_builtin && value.add_mod_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::add_mod, + )); + } + if !value.uses_mul_mod_builtin && value.mul_mod_ratio != 0 { + return Err(RunnerError::BadDynamicLayoutBuiltinRatio( + BuiltinName::mul_mod, + )); + } + + Ok(CairoLayoutParams { + rc_units: value.rc_units, + log_diluted_units_per_step: value.log_diluted_units_per_step, + cpu_component_step: value.cpu_component_step, + memory_units_per_step: value.memory_units_per_step, + range_check96_ratio_den: value.range_check96_ratio_den, + mul_mod_ratio_den: value.mul_mod_ratio_den, + add_mod_ratio_den: value.add_mod_ratio_den, + pedersen_ratio: value.pedersen_ratio, + range_check_ratio: value.range_check_ratio, + ecdsa_ratio: value.ecdsa_ratio, + bitwise_ratio: value.bitwise_ratio, + ec_op_ratio: value.ec_op_ratio, + keccak_ratio: value.keccak_ratio, + poseidon_ratio: value.poseidon_ratio, + range_check96_ratio: value.range_check96_ratio, + add_mod_ratio: value.add_mod_ratio, + mul_mod_ratio: value.mul_mod_ratio, + }) + } +} + +fn bool_from_int_or_bool<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + #[serde(untagged)] + enum IntOrBool { + Int(i64), + Boolean(bool), + } + + match IntOrBool::deserialize(deserializer)? { + IntOrBool::Int(0) => Ok(false), + IntOrBool::Int(_) => Ok(true), + IntOrBool::Boolean(v) => Ok(v), } } #[cfg(test)] mod tests { use super::*; + #[cfg(feature = "mod_builtin")] + use crate::types::instance_definitions::mod_instance_def::ModInstanceDef; + use crate::types::instance_definitions::{ + bitwise_instance_def::BitwiseInstanceDef, ec_op_instance_def::EcOpInstanceDef, + ecdsa_instance_def::EcdsaInstanceDef, keccak_instance_def::KeccakInstanceDef, + pedersen_instance_def::PedersenInstanceDef, poseidon_instance_def::PoseidonInstanceDef, + range_check_instance_def::RangeCheckInstanceDef, + }; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; @@ -257,15 +449,130 @@ mod tests { #[test] fn get_dynamic_instance() { - let layout = CairoLayout::dynamic_instance(); - let builtins = BuiltinsInstanceDef::dynamic(); + // dummy cairo layout params + let params = CairoLayoutParams { + rc_units: 32, + log_diluted_units_per_step: 5, + pedersen_ratio: 32, + range_check_ratio: 32, + ecdsa_ratio: 32, + bitwise_ratio: 32, + ec_op_ratio: 32, + keccak_ratio: 32, + mul_mod_ratio: 32, + ..Default::default() // + // cpu_component_step: todo!(), + // memory_units_per_step: todo!(), + // range_check96_ratio_den: todo!(), + // add_mod_ratio_den: todo!(), + // mul_mod_ratio_den: todo!(), + }; + + let layout = CairoLayout::dynamic_instance(params); + assert_eq!(layout.name, LayoutName::dynamic); - assert_eq!(layout.rc_units, 16); - assert_eq!(layout.builtins, builtins); - assert_eq!(layout.public_memory_fraction, 8); + assert_eq!(layout.rc_units, 32); + assert_eq!(layout.public_memory_fraction, 8); // hardcoded assert_eq!( layout.diluted_pool_instance_def, - Some(DilutedPoolInstanceDef::default()) + Some(DilutedPoolInstanceDef { + units_per_step: 32, + ..DilutedPoolInstanceDef::default() // hardcoded + }) + ); + + assert!(layout.builtins.output); + assert_eq!( + layout.builtins.pedersen, + Some(PedersenInstanceDef { ratio: Some(32) }) + ); + assert_eq!( + layout.builtins.range_check, + Some(RangeCheckInstanceDef { ratio: Some(32) }) + ); + assert_eq!( + layout.builtins.ecdsa, + Some(EcdsaInstanceDef { ratio: Some(32) }) + ); + assert_eq!( + layout.builtins.bitwise, + Some(BitwiseInstanceDef { ratio: Some(32) }) + ); + assert_eq!( + layout.builtins.ec_op, + Some(EcOpInstanceDef { ratio: Some(32) }) + ); + assert_eq!( + layout.builtins.keccak, + Some(KeccakInstanceDef { ratio: Some(32) }) + ); + assert_eq!( + layout.builtins.poseidon, + Some(PoseidonInstanceDef { ratio: Some(0) }), ); + assert_eq!( + layout.builtins.range_check96, + Some(RangeCheckInstanceDef { ratio: Some(0) }) + ); + #[cfg(feature = "mod_builtin")] + { + assert_eq!( + layout.builtins.mul_mod, + Some(ModInstanceDef { + ratio: Some(32), + word_bit_len: 96, // hardcoded + batch_size: 1 // hardcoded + }), + ); + assert_eq!( + layout.builtins.add_mod, + Some(ModInstanceDef { + ratio: Some(0), + word_bit_len: 96, // hardcoded + batch_size: 1 // hardcoded + }) + ); + } + #[cfg(not(feature = "mod_builtin"))] + { + assert_eq!(layout.builtins.mul_mod, None,); + assert_eq!(layout.builtins.add_mod, None,); + } + } + + #[test] + fn parse_dynamic_instance() { + let cairo_layout_params_json = "{\n\ + \"rc_units\": 4,\n\ + \"log_diluted_units_per_step\": 4,\n\ + \"cpu_component_step\": 8,\n\ + \"memory_units_per_step\": 8,\n\ + \"uses_pedersen_builtin\": true,\n\ + \"pedersen_ratio\": 256,\n\ + \"uses_range_check_builtin\": true,\n\ + \"range_check_ratio\": 8,\n\ + \"uses_ecdsa_builtin\": true,\n\ + \"ecdsa_ratio\": 2048,\n\ + \"uses_bitwise_builtin\": true,\n\ + \"bitwise_ratio\": 16,\n\ + \"uses_ec_op_builtin\": true,\n\ + \"ec_op_ratio\": 1024,\n\ + \"uses_keccak_builtin\": true,\n\ + \"keccak_ratio\": 2048,\n\ + \"uses_poseidon_builtin\": true,\n\ + \"poseidon_ratio\": 256,\n\ + \"uses_range_check96_builtin\": true,\n\ + \"range_check96_ratio\": 8,\n\ + \"range_check96_ratio_den\": 1,\n\ + \"uses_add_mod_builtin\": true,\n\ + \"add_mod_ratio\": 128,\n\ + \"add_mod_ratio_den\": 1,\n\ + \"uses_mul_mod_builtin\": true,\n\ + \"mul_mod_ratio\": 256,\n\ + \"mul_mod_ratio_den\": 1\n\ + }\n\ + "; + + serde_json::from_str::(cairo_layout_params_json).unwrap(); } } diff --git a/vm/src/types/layout_name.rs b/vm/src/types/layout_name.rs index 8cfd792dc0..4082743f42 100644 --- a/vm/src/types/layout_name.rs +++ b/vm/src/types/layout_name.rs @@ -36,7 +36,7 @@ impl LayoutName { LayoutName::recursive_with_poseidon => "recursive_with_poseidon", LayoutName::all_solidity => "all_solidity", LayoutName::all_cairo => "all_cairo", - LayoutName::dynamic => "all_cairo", + LayoutName::dynamic => "dynamic", } } } diff --git a/vm/src/utils.rs b/vm/src/utils.rs index 070efcaf6d..760c5201ad 100644 --- a/vm/src/utils.rs +++ b/vm/src/utils.rs @@ -252,19 +252,23 @@ pub mod test_utils { crate::vm::runners::cairo_runner::CairoRunner::new( &$program, crate::types::layout_name::LayoutName::all_cairo, + None, false, false, ) .unwrap() }; ($program:expr, $layout:expr) => { - crate::vm::runners::cairo_runner::CairoRunner::new(&$program, $layout, false, false) - .unwrap() + crate::vm::runners::cairo_runner::CairoRunner::new( + &$program, $layout, None, false, false, + ) + .unwrap() }; ($program:expr, $layout:expr, $proof_mode:expr) => { crate::vm::runners::cairo_runner::CairoRunner::new( &$program, $layout, + None, $proof_mode, false, ) @@ -274,6 +278,7 @@ pub mod test_utils { crate::vm::runners::cairo_runner::CairoRunner::new( &$program, $layout, + None, $proof_mode, $trace_enabled, ) diff --git a/vm/src/vm/errors/runner_errors.rs b/vm/src/vm/errors/runner_errors.rs index 561f89997e..98c0787810 100644 --- a/vm/src/vm/errors/runner_errors.rs +++ b/vm/src/vm/errors/runner_errors.rs @@ -132,6 +132,10 @@ pub enum RunnerError { CairoPieProofMode, #[error("{0}: Invalid additional data")] InvalidAdditionalData(BuiltinName), + #[error("dynamic layout params is missing")] + MissingDynamicLayoutParams, + #[error("dynamic layout {0} ratio should be 0 when disabled")] + BadDynamicLayoutBuiltinRatio(BuiltinName), } #[cfg(test)] diff --git a/vm/src/vm/runners/builtin_runner/modulo.rs b/vm/src/vm/runners/builtin_runner/modulo.rs index b4aa0b7fa6..572ccf1897 100644 --- a/vm/src/vm/runners/builtin_runner/modulo.rs +++ b/vm/src/vm/runners/builtin_runner/modulo.rs @@ -699,7 +699,8 @@ mod tests { let mut hint_processor = BuiltinHintProcessor::new_empty(); let program = Program::from_bytes(program_data, Some("main")).unwrap(); - let mut runner = CairoRunner::new(&program, LayoutName::all_cairo, true, false).unwrap(); + let mut runner = + CairoRunner::new(&program, LayoutName::all_cairo, None, true, false).unwrap(); let end = runner.initialize(false).unwrap(); // Modify add_mod & mul_mod params diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index ecf47892b0..a283885d57 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -1,13 +1,18 @@ use crate::{ air_private_input::AirPrivateInput, air_public_input::{PublicInput, PublicInputError}, + math_utils::safe_div_usize, stdlib::{ any::Any, collections::{HashMap, HashSet}, ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}, prelude::*, }, - types::{builtin_name::BuiltinName, layout::MEMORY_UNITS_PER_STEP, layout_name::LayoutName}, + types::{ + builtin_name::BuiltinName, + layout::{CairoLayoutParams, MEMORY_UNITS_PER_STEP}, + layout_name::LayoutName, + }, vm::{ runners::builtin_runner::SegmentArenaBuiltinRunner, trace::trace_entry::{relocate_trace_register, RelocatedTraceEntry}, @@ -17,7 +22,6 @@ use crate::{ use crate::{ hint_processor::hint_processor_definition::{HintProcessor, HintReference}, - math_utils::safe_div_usize, types::{ errors::{math_errors::MathError, program_errors::ProgramError}, exec_scope::ExecutionScopes, @@ -168,9 +172,12 @@ pub enum RunnerMode { } impl CairoRunner { + /// The `dynamic_layout_params` argument should only be used with dynamic layout. + /// It is ignored otherwise. pub fn new_v2( program: &Program, layout: LayoutName, + dynamic_layout_params: Option, mode: RunnerMode, trace_enabled: bool, ) -> Result { @@ -185,7 +192,12 @@ impl CairoRunner { LayoutName::recursive_with_poseidon => CairoLayout::recursive_with_poseidon(), LayoutName::all_cairo => CairoLayout::all_cairo_instance(), LayoutName::all_solidity => CairoLayout::all_solidity_instance(), - LayoutName::dynamic => CairoLayout::dynamic_instance(), + LayoutName::dynamic => { + let params = + dynamic_layout_params.ok_or(RunnerError::MissingDynamicLayoutParams)?; + + CairoLayout::dynamic_instance(params) + } }; Ok(CairoRunner { program: program.clone(), @@ -215,6 +227,7 @@ impl CairoRunner { pub fn new( program: &Program, layout: LayoutName, + dynamic_layout_params: Option, proof_mode: bool, trace_enabled: bool, ) -> Result { @@ -222,11 +235,18 @@ impl CairoRunner { Self::new_v2( program, layout, + dynamic_layout_params, RunnerMode::ProofModeCanonical, trace_enabled, ) } else { - Self::new_v2(program, layout, RunnerMode::ExecutionMode, trace_enabled) + Self::new_v2( + program, + layout, + dynamic_layout_params, + RunnerMode::ExecutionMode, + trace_enabled, + ) } } @@ -826,6 +846,7 @@ impl CairoRunner { self.vm.current_step, builtin_runner.ratio().unwrap_or(1) as usize, )?; + used_units_by_builtins += used_units * multiplier; } From 7d19956781901fb05c76f7c02fa82bd907f0f9a2 Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Mon, 30 Sep 2024 18:14:10 -0300 Subject: [PATCH 02/34] Fix modulo builtin constraints (#1841) * Fix Zero segment location. * Fixed has_zero_segment naming * Fix prover input. * Fixed version reading when no version is supplied * Added change to changelog. * fix test_from_serializable() * fix panic_impl error * fix cairo version * Add dummy changelog * Pin wasm-bindgen * Register change in CHANGELOG * Update Cargo.lock * Remove changes from CHANGELOG * Add argument parsing for layout params file * Add dynamic support (no implement) * Add cairo_layout_params_file.example.json * Implement dynamic layout creation * Update CHANGELOG * Add cli dynamic support for cairo 1 * Make wasm compatible * Use public_memory_fraction = 4 vy default * Deserialize bool from int * Add comparison with python-vm (failing) * Rebuild .rs files in makefile * Use 8 as dynamic public_memory_fraction The same value is used in python-vm * Use None ratio for dynamic unused builtins * Add rangecheck96 to private inputs * Make dyn py files depend on params_file * Use cpu_component_step=1 by default * Fix typo in private inputs * Add range check value to air private input test * Fix zero segment location * Use zero builtin instead of None * Add debug scripts * Remove dup makefile recipes * remove outdated test * Enable ensure-no_std on test * Fix tests * Add correct test * Rename tset * Add comment * Add debugging document * Update cairo layout params file * Remove duplicated range check * Remove dup * Remove debugging and scrippts (moveed to another branch) * Add comment * Add tests * Add dynamic test to cairo-vm-cli * Add parse test * Remove compare all dynamic * Add script for comparing with dynamic layouts * Add tests to workflow * Delete logic changes They are going to be moved to another branch * Delete more logic changes * Update rust.yml * Rename compare_outputs_dynamic_layout.sh to compare_outputs_dynamic_layouts.sh * Update test script * Enforce prover constraints in add, sub, and mul * Remove debug prints * Add tests * Update CHANGELOG.md * Fix serialization * Comment failing test * Uncomment test * Fix tests * Remove operation struct and use builtin type instead * Add unit tests to modulo builtin operations * Fix security error message * Test custom serde impl * Upload mod_builtin coverage --------- Co-authored-by: Alon Titelman Co-authored-by: Yuval Goldberg Co-authored-by: Omri Eshhar --- .github/workflows/rust.yml | 30 ++ CHANGELOG.md | 3 + vm/src/air_private_input.rs | 84 ++++++ .../tests/compare_outputs_dynamic_layouts.sh | 3 + vm/src/vm/runners/builtin_runner/modulo.rs | 261 +++++++++++++----- 5 files changed, 306 insertions(+), 75 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6dde21ab95..600b0e52ca 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -600,6 +600,36 @@ jobs: key: codecov-cache-test-no_std-extensive_hints-${{ github.sha }} fail-on-cache-miss: true + - name: Fetch results for tests with stdlib (w/mod_builtin; part. 1) + uses: actions/cache/restore@v3 + with: + path: lcov-test#1-mod_builtin.info + key: codecov-cache-test#1-mod_builtin-${{ github.sha }} + fail-on-cache-miss: true + - name: Fetch results for tests with stdlib (w/mod_builtin; part. 2) + uses: actions/cache/restore@v3 + with: + path: lcov-test#2-mod_builtin.info + key: codecov-cache-test#2-mod_builtin-${{ github.sha }} + fail-on-cache-miss: true + - name: Fetch results for tests with stdlib (w/mod_builtin; part. 3) + uses: actions/cache/restore@v3 + with: + path: lcov-test#3-mod_builtin.info + key: codecov-cache-test#3-mod_builtin-${{ github.sha }} + fail-on-cache-miss: true + - name: Fetch results for tests with stdlib (w/mod_builtin; part. 4) + uses: actions/cache/restore@v3 + with: + path: lcov-test#4-mod_builtin.info + key: codecov-cache-test#4-mod_builtin-${{ github.sha }} + fail-on-cache-miss: true + - name: Fetch results for tests without stdlib (w/mod_builtin) + uses: actions/cache/restore@v3 + with: + path: lcov-no_std-mod_builtin.info + key: codecov-cache-test-no_std-mod_builtin-${{ github.sha }} + fail-on-cache-miss: true - name: Upload coverage to codecov.io uses: codecov/codecov-action@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3317000d50..1f4001b5a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ #### Upcoming Changes +* fix: [#1841](https://github.com/lambdaclass/cairo-vm/pull/1841): + * Fix modulo builtin to comply with prover constraints + * feat(BREAKING): [#1824](https://github.com/lambdaclass/cairo-vm/pull/1824): * Add support for dynamic layout * CLI change(BREAKING): The flag `cairo_layout_params_file` must be specified when using dynamic layout. diff --git a/vm/src/air_private_input.rs b/vm/src/air_private_input.rs index b76575eaff..421c1b3fa0 100644 --- a/vm/src/air_private_input.rs +++ b/vm/src/air_private_input.rs @@ -126,6 +126,8 @@ pub struct ModInputInstance { pub values_ptr: usize, pub offsets_ptr: usize, pub n: usize, + #[serde(deserialize_with = "mod_input_instance_batch_serde::deserialize")] + #[serde(serialize_with = "mod_input_instance_batch_serde::serialize")] pub batch: BTreeMap, } @@ -205,6 +207,88 @@ impl AirPrivateInputSerializable { } } +mod mod_input_instance_batch_serde { + use super::*; + + use serde::{Deserializer, Serializer}; + + pub(crate) fn serialize( + value: &BTreeMap, + s: S, + ) -> Result { + let value = value.iter().map(|v| v.1).collect::>(); + + value.serialize(s) + } + + pub(crate) fn deserialize<'de, D: Deserializer<'de>>( + d: D, + ) -> Result, D::Error> { + let value = Vec::::deserialize(d)?; + + Ok(value.into_iter().enumerate().collect()) + } + + #[cfg(feature = "std")] + #[test] + fn test_serde() { + let input_value = vec![ + ( + 0, + ModInputMemoryVars { + a_offset: 5, + b_offset: 5, + c_offset: 5, + a0: Felt252::from(5u32), + a1: Felt252::from(5u32), + a2: Felt252::from(5u32), + a3: Felt252::from(5u32), + b0: Felt252::from(5u32), + b1: Felt252::from(5u32), + b2: Felt252::from(5u32), + b3: Felt252::from(5u32), + c0: Felt252::from(5u32), + c1: Felt252::from(5u32), + c2: Felt252::from(5u32), + c3: Felt252::from(5u32), + }, + ), + ( + 1, + ModInputMemoryVars { + a_offset: 7, + b_offset: 7, + c_offset: 7, + a0: Felt252::from(7u32), + a1: Felt252::from(7u32), + a2: Felt252::from(7u32), + a3: Felt252::from(7u32), + b0: Felt252::from(7u32), + b1: Felt252::from(7u32), + b2: Felt252::from(7u32), + b3: Felt252::from(7u32), + c0: Felt252::from(7u32), + c1: Felt252::from(7u32), + c2: Felt252::from(7u32), + c3: Felt252::from(7u32), + }, + ), + ] + .into_iter() + .collect::>(); + + let bytes = Vec::new(); + let mut serializer = serde_json::Serializer::new(bytes); + serialize(&input_value, &mut serializer).unwrap(); + let bytes = serializer.into_inner(); + + let mut deserializer = serde_json::Deserializer::from_slice(&bytes); + let output_value = deserialize(&mut deserializer).unwrap(); + + assert_eq!(input_value, output_value); + } +} + #[cfg(test)] mod tests { use crate::types::layout_name::LayoutName; diff --git a/vm/src/tests/compare_outputs_dynamic_layouts.sh b/vm/src/tests/compare_outputs_dynamic_layouts.sh index 7077edaa44..2bc512e3a1 100755 --- a/vm/src/tests/compare_outputs_dynamic_layouts.sh +++ b/vm/src/tests/compare_outputs_dynamic_layouts.sh @@ -82,6 +82,9 @@ CASES=( "cairo_programs/proof_programs/sha256.json;double_all_cairo" "cairo_programs/proof_programs/keccak.json;all_cairo" "cairo_programs/proof_programs/keccak.json;double_all_cairo" + "cairo_programs/mod_builtin_feature/proof/mod_builtin.json;all_cairo" + "cairo_programs/mod_builtin_feature/proof/mod_builtin_failure.json;all_cairo" + "cairo_programs/mod_builtin_feature/proof/apply_poly.json;all_cairo" ) passed_tests=0 diff --git a/vm/src/vm/runners/builtin_runner/modulo.rs b/vm/src/vm/runners/builtin_runner/modulo.rs index 572ccf1897..0f5bb7719b 100644 --- a/vm/src/vm/runners/builtin_runner/modulo.rs +++ b/vm/src/vm/runners/builtin_runner/modulo.rs @@ -21,7 +21,7 @@ use crate::{ }, Felt252, }; -use core::{fmt::Display, ops::Shl}; +use core::ops::Shl; use num_bigint::BigUint; use num_integer::div_ceil; use num_integer::Integer; @@ -47,6 +47,7 @@ pub struct ModBuiltinRunner { // Precomputed powers used for reading and writing values that are represented as n_words words of word_bit_len bits each. shift: BigUint, shift_powers: [BigUint; N_WORDS], + k_bound: BigUint, } #[derive(Debug, Clone)] @@ -55,21 +56,11 @@ pub enum ModBuiltinType { Add, } -#[derive(Debug)] -pub enum Operation { - Mul, - Add, - Sub, - DivMod(BigUint), -} - -impl Display for Operation { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { +impl ModBuiltinType { + pub(crate) fn operation_string(&self) -> &'static str { match self { - Operation::Mul => "*".fmt(f), - Operation::Add => "+".fmt(f), - Operation::Sub => "-".fmt(f), - Operation::DivMod(_) => "/".fmt(f), + ModBuiltinType::Mul => "*", + ModBuiltinType::Add => "+", } } } @@ -85,17 +76,28 @@ struct Inputs { impl ModBuiltinRunner { pub(crate) fn new_add_mod(instance_def: &ModInstanceDef, included: bool) -> Self { - Self::new(instance_def.clone(), included, ModBuiltinType::Add) + Self::new( + instance_def.clone(), + included, + ModBuiltinType::Add, + Some(2u32.into()), + ) } pub(crate) fn new_mul_mod(instance_def: &ModInstanceDef, included: bool) -> Self { - Self::new(instance_def.clone(), included, ModBuiltinType::Mul) + Self::new(instance_def.clone(), included, ModBuiltinType::Mul, None) } - fn new(instance_def: ModInstanceDef, included: bool, builtin_type: ModBuiltinType) -> Self { + fn new( + instance_def: ModInstanceDef, + included: bool, + builtin_type: ModBuiltinType, + k_bound: Option, + ) -> Self { let shift = BigUint::one().shl(instance_def.word_bit_len); let shift_powers = core::array::from_fn(|i| shift.pow(i as u32)); let zero_segment_size = core::cmp::max(N_WORDS, instance_def.batch_size * 3); + let int_lim = BigUint::from(2_u32).pow(N_WORDS as u32 * instance_def.word_bit_len); Self { builtin_type, base: 0, @@ -106,6 +108,7 @@ impl ModBuiltinRunner { zero_segment_size, shift, shift_powers, + k_bound: k_bound.unwrap_or(int_lim), } } @@ -435,13 +438,13 @@ impl ModBuiltinRunner { // Fills a value in the values table, if exactly one value is missing. // Returns true on success or if all values are already known. + // + // The builtin type (add or mul) determines which operation to perform fn fill_value( &self, memory: &mut Memory, inputs: &Inputs, index: usize, - op: &Operation, - inv_op: &Operation, ) -> Result { let mut addresses = Vec::new(); let mut values = Vec::new(); @@ -458,19 +461,19 @@ impl ModBuiltinRunner { match (a, b, c) { // Deduce c from a and b and write it to memory. (Some(a), Some(b), None) => { - let value = apply_op(a, b, op)?.mod_floor(&inputs.p); + let value = self.apply_operation(a, b, &inputs.p)?; self.write_n_words_value(memory, addresses[2], value)?; Ok(true) } // Deduce b from a and c and write it to memory. (Some(a), None, Some(c)) => { - let value = apply_op(c, a, inv_op)?.mod_floor(&inputs.p); + let value = self.deduce_operand(a, c, &inputs.p)?; self.write_n_words_value(memory, addresses[1], value)?; Ok(true) } // Deduce a from b and c and write it to memory. (None, Some(b), Some(c)) => { - let value = apply_op(c, b, inv_op)?.mod_floor(&inputs.p); + let value = self.deduce_operand(b, c, &inputs.p)?; self.write_n_words_value(memory, addresses[0], value)?; Ok(true) } @@ -539,44 +542,33 @@ impl ModBuiltinRunner { Default::default() }; - // Get one of the builtin runners - the rest of this function doesn't depend on batch_size. - let mod_runner = if let Some((_, add_mod, _)) = add_mod { - add_mod - } else { - mul_mod.unwrap().1 - }; // Fill the values table. let mut add_mod_index = 0; let mut mul_mod_index = 0; - // Create operation here to avoid cloning p in the loop - let div_operation = Operation::DivMod(mul_mod_inputs.p.clone()); + while add_mod_index < add_mod_n || mul_mod_index < mul_mod_n { - if add_mod_index < add_mod_n - && mod_runner.fill_value( - memory, - &add_mod_inputs, - add_mod_index, - &Operation::Add, - &Operation::Sub, - )? - { - add_mod_index += 1; - } else if mul_mod_index < mul_mod_n - && mod_runner.fill_value( - memory, - &mul_mod_inputs, - mul_mod_index, - &Operation::Mul, - &div_operation, - )? - { - mul_mod_index += 1; - } else { - return Err(RunnerError::FillMemoryCoudNotFillTable( - add_mod_index, - mul_mod_index, - )); + if add_mod_index < add_mod_n { + if let Some((_, add_mod_runner, _)) = add_mod { + if add_mod_runner.fill_value(memory, &add_mod_inputs, add_mod_index)? { + add_mod_index += 1; + continue; + } + } } + + if mul_mod_index < mul_mod_n { + if let Some((_, mul_mod_runner, _)) = mul_mod { + if mul_mod_runner.fill_value(memory, &mul_mod_inputs, mul_mod_index)? { + mul_mod_index += 1; + } + continue; + } + } + + return Err(RunnerError::FillMemoryCoudNotFillTable( + add_mod_index, + mul_mod_index, + )); } Ok(()) } @@ -625,14 +617,11 @@ impl ModBuiltinRunner { inputs.offsets_ptr, index_in_batch, )?; - let op = match self.builtin_type { - ModBuiltinType::Add => Operation::Add, - ModBuiltinType::Mul => Operation::Mul, - }; - let a_op_b = apply_op(&a, &b, &op)?.mod_floor(&inputs.p); - if a_op_b != c.mod_floor(&inputs.p) { + let a_op_b = self.apply_operation(&a, &b, &inputs.p)?; + if a_op_b.mod_floor(&inputs.p) != c.mod_floor(&inputs.p) { // Build error string let p = inputs.p; + let op = self.builtin_type.operation_string(); let error_string = format!("Expected a {op} b == c (mod p). Got: instance={instance}, batch={index_in_batch}, p={p}, a={a}, b={b}, c={c}."); return Err(RunnerError::ModBuiltinSecurityCheck(Box::new(( self.name(), @@ -667,23 +656,145 @@ impl ModBuiltinRunner { self.shift_powers = core::array::from_fn(|i| self.shift.pow(i as u32)); self.zero_segment_size = core::cmp::max(N_WORDS, batch_size * 3); } -} -fn apply_op(lhs: &BigUint, rhs: &BigUint, op: &Operation) -> Result { - Ok(match op { - Operation::Mul => lhs * rhs, - Operation::Add => lhs + rhs, - Operation::Sub => lhs - rhs, - Operation::DivMod(ref p) => div_mod_unsigned(lhs, rhs, p)?, - }) + // Calculates the result of `lhs OP rhs` + // + // The builtin type (add or mul) determines the OP + pub(crate) fn apply_operation( + &self, + lhs: &BigUint, + rhs: &BigUint, + prime: &BigUint, + ) -> Result { + let full_value = match self.builtin_type { + ModBuiltinType::Mul => lhs * rhs, + ModBuiltinType::Add => lhs + rhs, + }; + + let value = if full_value < &self.k_bound * prime { + full_value.mod_floor(prime) + } else { + full_value - (&self.k_bound - 1u32) * prime + }; + + Ok(value) + } + + // Given `known OP unknown = result (mod p)`, it deduces `unknown` + // + // The builtin type (add or mul) determines the OP + pub(crate) fn deduce_operand( + &self, + known: &BigUint, + result: &BigUint, + prime: &BigUint, + ) -> Result { + let value = match self.builtin_type { + ModBuiltinType::Add => { + if known <= result { + result - known + } else { + result + prime - known + } + } + ModBuiltinType::Mul => div_mod_unsigned(result, known, prime)?, + }; + Ok(value) + } } #[cfg(test)] mod tests { + use super::*; + + #[test] + fn apply_operation_add() { + let builtin = ModBuiltinRunner::new_add_mod(&ModInstanceDef::new(Some(8), 8, 8), true); + + assert_eq!( + builtin + .apply_operation( + &BigUint::from(2u32), + &BigUint::from(3u32), + &BigUint::from(7u32) + ) + .unwrap(), + BigUint::from(5u32) + ); + + assert_eq!( + builtin + .apply_operation( + &BigUint::from(5u32), + &BigUint::from(5u32), + &BigUint::from(5u32) + ) + .unwrap(), + BigUint::from(5u32) + ); + } + + #[test] + fn apply_operation_mul() { + let builtin = ModBuiltinRunner::new_mul_mod(&ModInstanceDef::new(Some(8), 8, 8), true); + + assert_eq!( + builtin + .apply_operation( + &BigUint::from(2u32), + &BigUint::from(3u32), + &BigUint::from(7u32) + ) + .unwrap(), + BigUint::from(6u32) + ); + } + + #[test] + fn deduce_operand_add() { + let builtin = ModBuiltinRunner::new_add_mod(&ModInstanceDef::new(Some(8), 8, 8), true); + + assert_eq!( + builtin + .deduce_operand( + &BigUint::from(2u32), + &BigUint::from(5u32), + &BigUint::from(7u32) + ) + .unwrap(), + BigUint::from(3u32) + ); + assert_eq!( + builtin + .deduce_operand( + &BigUint::from(5u32), + &BigUint::from(2u32), + &BigUint::from(7u32) + ) + .unwrap(), + BigUint::from(4u32) + ); + } + + #[test] + fn deduce_operand_mul() { + let builtin = ModBuiltinRunner::new_mul_mod(&ModInstanceDef::new(Some(8), 8, 8), true); + + assert_eq!( + builtin + .deduce_operand( + &BigUint::from(2u32), + &BigUint::from(1u32), + &BigUint::from(7u32) + ) + .unwrap(), + BigUint::from(4u32) + ); + } + #[test] #[cfg(feature = "mod_builtin")] fn test_air_private_input_all_cairo() { - use super::*; use crate::{ air_private_input::{ModInput, ModInputInstance, ModInputMemoryVars, PrivateInput}, hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, @@ -735,8 +846,8 @@ mod tests { a2: Felt252::ZERO, a3: Felt252::ZERO, b_offset: 12, - b0: Felt252::ZERO, - b1: Felt252::ZERO, + b0: Felt252::ONE, + b1: Felt252::ONE, b2: Felt252::ZERO, b3: Felt252::ZERO, c_offset: 4, @@ -798,8 +909,8 @@ mod tests { 0, ModInputMemoryVars { a_offset: 12, - a0: Felt252::ZERO, - a1: Felt252::ZERO, + a0: Felt252::ONE, + a1: Felt252::ONE, a2: Felt252::ZERO, a3: Felt252::ZERO, b_offset: 8, From 3fb0344ce038b3a68cae897c403d1f561cfe8da7 Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Fri, 4 Oct 2024 12:34:34 -0300 Subject: [PATCH 03/34] Missing dynamic layout features (#1838) * Fix Zero segment location. * Fixed has_zero_segment naming * Fix prover input. * Fixed version reading when no version is supplied * Added change to changelog. * fix test_from_serializable() * fix panic_impl error * fix cairo version * Add dummy changelog * Pin wasm-bindgen * Register change in CHANGELOG * Update Cargo.lock * Remove changes from CHANGELOG * Add argument parsing for layout params file * Add dynamic support (no implement) * Add cairo_layout_params_file.example.json * Implement dynamic layout creation * Update CHANGELOG * Add cli dynamic support for cairo 1 * Make wasm compatible * Use public_memory_fraction = 4 vy default * Deserialize bool from int * Add comparison with python-vm (failing) * Rebuild .rs files in makefile * Use 8 as dynamic public_memory_fraction The same value is used in python-vm * Use None ratio for dynamic unused builtins * Add rangecheck96 to private inputs * Make dyn py files depend on params_file * Use cpu_component_step=1 by default * Fix typo in private inputs * Add range check value to air private input test * Fix zero segment location * Use zero builtin instead of None * Add debug scripts * Remove dup makefile recipes * remove outdated test * Enable ensure-no_std on test * Fix tests * Add correct test * Rename tset * Add comment * Add debugging document * Update cairo layout params file * Remove duplicated range check * Remove dup * Add support for dynamic memory units per step * Add changelog * Add support for negative log units per step * Add LowRatio struct to RangeCheck and Mod builtins * Fix test * Use ratio_den in get_allocated_instances * Remove debugging and scrippts (moveed to another branch) * Add comment * Add tests * Add dynamic test to cairo-vm-cli * Add parse test * Remove compare all dynamic * Add script for comparing with dynamic layouts * Add tests to workflow * Delete logic changes They are going to be moved to another branch * Delete more logic changes * Reorder fields * Remove ref * Add modulo tests with all_cairo * Add tests * Update rust.yml * Rename compare_outputs_dynamic_layout.sh to compare_outputs_dynamic_layouts.sh * Update test script * Remove tests * Enforce prover constraints in add, sub, and mul * Remove debug prints * Add tests * Update CHANGELOG.md * Fix serialization * Comment failing test * Uncomment test * Add fractional units per step test * Change safe_div for div_ceil (bug) * Add ratio_den tests * Fix tests * Remove operation struct and use builtin type instead * Add unit tests to modulo builtin operations * Fix security error message * Add mod_builtin to coverage * Test custom serde impl * Upload mod_builtin coverage * Test custom serde impl * Upload mod_builtin coverage * Add Debug scripts (#1839) * Add debug scripts * Add debugging document * Add changelog * Revert changelog * Improve script usage code blocks * Remove extra space * Add cpu_component_step * Add comments * Add cairo pie tests * Restore zip * Use .rs.pie.zip * Update Changelog * Add dynamic layout documentation * Update CHANGELOG.md --------- Co-authored-by: Alon Titelman Co-authored-by: Yuval Goldberg Co-authored-by: Omri Eshhar Co-authored-by: Pedro Fontana --- .github/workflows/rust.yml | 14 +- CHANGELOG.md | 8 +- README.md | 9 ++ .../tests/compare_outputs_dynamic_layouts.sh | 133 ++++++++++++++++++ .../builtins_instance_def.rs | 18 ++- .../diluted_pool_instance_def.rs | 11 ++ vm/src/types/instance_definitions/mod.rs | 24 ++++ .../instance_definitions/mod_instance_def.rs | 25 +++- .../range_check_instance_def.rs | 20 ++- vm/src/types/layout.rs | 93 ++++++++---- vm/src/vm/runners/builtin_runner/mod.rs | 100 +++++++++++-- vm/src/vm/runners/builtin_runner/modulo.rs | 6 +- .../vm/runners/builtin_runner/range_check.rs | 22 ++- vm/src/vm/runners/cairo_runner.rs | 32 +++-- 14 files changed, 443 insertions(+), 72 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 600b0e52ca..18cdb5653d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -757,7 +757,7 @@ jobs: compare-outputs-dynamic-layouts: name: Compare outputs with dynamic layouts - needs: [ build-programs, build-release ] + needs: [ build-programs, build-release, run-cairo-release ] runs-on: ubuntu-22.04 steps: - name: Checkout @@ -791,6 +791,18 @@ jobs: key: cairo_proof_programs-cache-${{ hashFiles('cairo_programs/**/*.cairo', 'examples/wasm-demo/src/array_sum.cairo') }} fail-on-cache-miss: true + - name: Fetch pie + uses: actions/cache/restore@v3 + with: + path: | + cairo_programs/**/*.memory + cairo_programs/**/*.trace + cairo_programs/**/*.air_public_input + cairo_programs/**/*.air_private_input + cairo_programs/**/*.pie.zip + key: cairo_test_programs-release-trace-cache-${{ github.sha }} + fail-on-cache-miss: true + - name: Run script run: ./vm/src/tests/compare_outputs_dynamic_layouts.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f4001b5a7..4e19803711 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,14 @@ #### Upcoming Changes -* fix: [#1841](https://github.com/lambdaclass/cairo-vm/pull/1841): - * Fix modulo builtin to comply with prover constraints - -* feat(BREAKING): [#1824](https://github.com/lambdaclass/cairo-vm/pull/1824): +* feat(BREAKING): [#1824](https://github.com/lambdaclass/cairo-vm/pull/1824)[#1838](https://github.com/lambdaclass/cairo-vm/pull/1838): * Add support for dynamic layout * CLI change(BREAKING): The flag `cairo_layout_params_file` must be specified when using dynamic layout. * Signature change(BREAKING): Both `CairoRunner::new` and `CairoRunner::new_v2` now receive an `Option`, used only with dynamic layout. +* fix: [#1841](https://github.com/lambdaclass/cairo-vm/pull/1841): + * Fix modulo builtin to comply with prover constraints + * chore: bump pip `cairo-lang` 0.13.2 [#1827](https://github.com/lambdaclass/cairo-vm/pull/1827) * chore: bump `cairo-lang-` dependencies to 2.8.0 [#1833](https://github.com/lambdaclass/cairo-vm/pull/1833/files) diff --git a/README.md b/README.md index a7ecf920dc..ffae28ccdf 100644 --- a/README.md +++ b/README.md @@ -266,6 +266,15 @@ Now that you have the dependencies necessary to run the test suite you can run: make test ``` +### Using a Dynamic Layout + +A dynamic layout must be specified with a dynamic params file. You can find an example in: `vm/src/tests/cairo_layout_params_file.json`. + +To run cairo 0 or 1 programs with a dynamic layout, you must use `--layout dynamic` and the `--cairo_layout_params_file` flag pointing a dynamic params file. For example, run: +```bash +cargo run --bin cairo-vm-cli cairo_programs/fibonacci.json --layout dynamic --cairo_layout_params_file vm/src/tests/cairo_layout_params_file.json +``` + ### Tracer Cairo-vm offers a tracer which gives you a visualization of how your memory and registers change line after line as the VM executes the code. You can read more about it [here](./docs/tracer/README.md) diff --git a/vm/src/tests/compare_outputs_dynamic_layouts.sh b/vm/src/tests/compare_outputs_dynamic_layouts.sh index 2bc512e3a1..41c7bf0f17 100755 --- a/vm/src/tests/compare_outputs_dynamic_layouts.sh +++ b/vm/src/tests/compare_outputs_dynamic_layouts.sh @@ -68,6 +68,70 @@ cat < "$TEMP_FOLDER/double_all_cairo.json" } EOF +cat < "$TEMP_FOLDER/fractional_units_per_step.json" +{ + "rc_units": 4, + "log_diluted_units_per_step": -2, + "cpu_component_step": 8, + "memory_units_per_step": 8, + "uses_pedersen_builtin": false, + "pedersen_ratio": 0, + "uses_range_check_builtin": false, + "range_check_ratio": 0, + "uses_ecdsa_builtin": false, + "ecdsa_ratio": 0, + "uses_bitwise_builtin": false, + "bitwise_ratio": 0, + "uses_ec_op_builtin": false, + "ec_op_ratio": 0, + "uses_keccak_builtin": false, + "keccak_ratio": 0, + "uses_poseidon_builtin": false, + "poseidon_ratio": 0, + "uses_range_check96_builtin": false, + "range_check96_ratio": 0, + "range_check96_ratio_den": 1, + "uses_add_mod_builtin": false, + "add_mod_ratio": 0, + "add_mod_ratio_den": 1, + "uses_mul_mod_builtin": false, + "mul_mod_ratio": 0, + "mul_mod_ratio_den": 1 +} +EOF + +cat < "$TEMP_FOLDER/ratio_den.json" +{ + "rc_units": 4, + "log_diluted_units_per_step": 4, + "cpu_component_step": 8, + "memory_units_per_step": 512, + "uses_pedersen_builtin": false, + "pedersen_ratio": 0, + "uses_range_check_builtin": false, + "range_check_ratio": 0, + "uses_ecdsa_builtin": false, + "ecdsa_ratio": 0, + "uses_bitwise_builtin": false, + "bitwise_ratio": 0, + "uses_ec_op_builtin": false, + "ec_op_ratio": 0, + "uses_keccak_builtin": false, + "keccak_ratio": 0, + "uses_poseidon_builtin": false, + "poseidon_ratio": 0, + "uses_range_check96_builtin": true, + "range_check96_ratio": 1, + "range_check96_ratio_den": 2, + "uses_add_mod_builtin": true, + "add_mod_ratio": 1, + "add_mod_ratio_den": 2, + "uses_mul_mod_builtin": true, + "mul_mod_ratio": 1, + "mul_mod_ratio_den": 2 +} +EOF + # Build cases to execute CASES=( "cairo_programs/proof_programs/factorial.json;all_cairo" @@ -82,9 +146,33 @@ CASES=( "cairo_programs/proof_programs/sha256.json;double_all_cairo" "cairo_programs/proof_programs/keccak.json;all_cairo" "cairo_programs/proof_programs/keccak.json;double_all_cairo" + # Mod builtin feature "cairo_programs/mod_builtin_feature/proof/mod_builtin.json;all_cairo" "cairo_programs/mod_builtin_feature/proof/mod_builtin_failure.json;all_cairo" "cairo_programs/mod_builtin_feature/proof/apply_poly.json;all_cairo" + # Fractional units per step + "cairo_programs/proof_programs/factorial.json;fractional_units_per_step" + "cairo_programs/proof_programs/fibonacci.json;fractional_units_per_step" + # Ratio den + "cairo_programs/mod_builtin_feature/proof/mod_builtin.json;ratio_den" + "cairo_programs/mod_builtin_feature/proof/mod_builtin_failure.json;ratio_den" + "cairo_programs/mod_builtin_feature/proof/apply_poly.json;ratio_den" +) + +# Build pie cases to execute +PIE_CASES=( + "cairo_programs/fibonacci.rs.pie.zip;all_cairo" + "cairo_programs/fibonacci.rs.pie.zip;double_all_cairo" + "cairo_programs/factorial.rs.pie.zip;all_cairo" + "cairo_programs/factorial.rs.pie.zip;double_all_cairo" + "cairo_programs/bigint.rs.pie.zip;all_cairo" + "cairo_programs/bigint.rs.pie.zip;double_all_cairo" + "cairo_programs/dict.rs.pie.zip;all_cairo" + "cairo_programs/dict.rs.pie.zip;double_all_cairo" + "cairo_programs/sha256.rs.pie.zip;all_cairo" + "cairo_programs/sha256.rs.pie.zip;double_all_cairo" + "cairo_programs/keccak.rs.pie.zip;all_cairo" + "cairo_programs/keccak.rs.pie.zip;double_all_cairo" ) passed_tests=0 @@ -155,6 +243,51 @@ for case in "${CASES[@]}"; do rm program_py.* done + +for case in "${PIE_CASES[@]}"; do + IFS=";" read -r program layout <<< "$case" + + full_program="$program" + full_layout="$TEMP_FOLDER/$layout.json" + + # Run cairo-vm + echo "Running cairo-vm with case: $case" + cargo run -p cairo-vm-cli --features mod_builtin --release -- "$full_program" \ + --layout "dynamic" --cairo_layout_params_file "$full_layout" --run_from_cairo_pie \ + --trace_file program_rs.trace --memory_file program_rs.memory + + # Run cairo-lang + echo "Running cairo-lang with case: $case" + cairo-run --run_from_cairo_pie "$full_program" \ + --layout "dynamic" --cairo_layout_params_file "$full_layout" \ + --trace_file program_py.trace --memory_file program_py.memory + + # Compare trace + echo "Running trace comparison for case: $case" + if ! diff -q program_rs.trace program_py.trace; then + echo "Trace differs for case: $case" + exit_code=1 + failed_tests=$((failed_tests + 1)) + else + passed_tests=$((passed_tests + 1)) + fi + + # Compare memory + echo "Running memory comparison for case: $case" + if ! ./vm/src/tests/memory_comparator.py program_rs.memory program_py.memory; then + echo "Memory differs for case: $case" + exit_code=1 + failed_tests=$((failed_tests + 1)) + else + passed_tests=$((passed_tests + 1)) + fi + + # Clean files generated by the script + echo "Cleaning files" + rm program_rs.* + rm program_py.* +done + if test $failed_tests != 0; then echo "Comparisons: $failed_tests failed, $passed_tests passed, $((failed_tests + passed_tests)) total" elif test $passed_tests = 0; then diff --git a/vm/src/types/instance_definitions/builtins_instance_def.rs b/vm/src/types/instance_definitions/builtins_instance_def.rs index cf7d420636..bc33233af2 100644 --- a/vm/src/types/instance_definitions/builtins_instance_def.rs +++ b/vm/src/types/instance_definitions/builtins_instance_def.rs @@ -1,6 +1,7 @@ use crate::types::layout::CairoLayoutParams; use super::mod_instance_def::ModInstanceDef; +use super::LowRatio; use super::{ bitwise_instance_def::BitwiseInstanceDef, ec_op_instance_def::EcOpInstanceDef, ecdsa_instance_def::EcdsaInstanceDef, keccak_instance_def::KeccakInstanceDef, @@ -199,7 +200,7 @@ impl BuiltinsInstanceDef { ratio: Some(params.pedersen_ratio), }); let range_check = Some(RangeCheckInstanceDef { - ratio: Some(params.range_check_ratio), + ratio: Some(LowRatio::new_int(params.range_check_ratio)), }); let ecdsa = Some(EcdsaInstanceDef { ratio: Some(params.ecdsa_ratio), @@ -217,17 +218,26 @@ impl BuiltinsInstanceDef { ratio: Some(params.poseidon_ratio), }); let range_check96 = Some(RangeCheckInstanceDef { - ratio: Some(params.range_check96_ratio), + ratio: Some(LowRatio::new( + params.range_check96_ratio, + params.range_check96_ratio_den, + )), }); #[cfg(feature = "mod_builtin")] let add_mod = Some(ModInstanceDef { - ratio: Some(params.add_mod_ratio), + ratio: Some(LowRatio::new( + params.add_mod_ratio, + params.add_mod_ratio_den, + )), word_bit_len: 96, batch_size: 1, }); #[cfg(feature = "mod_builtin")] let mul_mod = Some(ModInstanceDef { - ratio: Some(params.mul_mod_ratio), + ratio: Some(LowRatio::new( + params.mul_mod_ratio, + params.mul_mod_ratio_den, + )), word_bit_len: 96, batch_size: 1, }); diff --git a/vm/src/types/instance_definitions/diluted_pool_instance_def.rs b/vm/src/types/instance_definitions/diluted_pool_instance_def.rs index 9be73a835d..d3c109b27d 100644 --- a/vm/src/types/instance_definitions/diluted_pool_instance_def.rs +++ b/vm/src/types/instance_definitions/diluted_pool_instance_def.rs @@ -3,6 +3,7 @@ use serde::Serialize; #[derive(Serialize, Debug, PartialEq)] pub(crate) struct DilutedPoolInstanceDef { pub(crate) units_per_step: u32, // 2 ^ log_units_per_step (for cairo_lang comparison) + pub(crate) fractional_units_per_step: bool, // true when log_units_per_step is negative pub(crate) spacing: u32, pub(crate) n_bits: u32, } @@ -11,6 +12,7 @@ impl DilutedPoolInstanceDef { pub(crate) fn default() -> Self { DilutedPoolInstanceDef { units_per_step: 16, + fractional_units_per_step: false, spacing: 4, n_bits: 16, } @@ -21,6 +23,15 @@ impl DilutedPoolInstanceDef { units_per_step, spacing, n_bits, + ..Self::default() + } + } + + pub(crate) fn from_log_units_per_step(log_units_per_step: i32) -> Self { + DilutedPoolInstanceDef { + units_per_step: 2_u32.pow(log_units_per_step.unsigned_abs()), + fractional_units_per_step: log_units_per_step.is_negative(), + ..DilutedPoolInstanceDef::default() } } } diff --git a/vm/src/types/instance_definitions/mod.rs b/vm/src/types/instance_definitions/mod.rs index 8f1bba2198..7884222c07 100644 --- a/vm/src/types/instance_definitions/mod.rs +++ b/vm/src/types/instance_definitions/mod.rs @@ -1,3 +1,5 @@ +use serde::Serialize; + pub mod bitwise_instance_def; pub mod builtins_instance_def; pub mod diluted_pool_instance_def; @@ -9,3 +11,25 @@ pub mod mod_instance_def; pub mod pedersen_instance_def; pub mod poseidon_instance_def; pub mod range_check_instance_def; + +#[derive(Serialize, Debug, PartialEq, Copy, Clone)] +pub struct LowRatio { + pub numerator: u32, + pub denominator: u32, +} + +impl LowRatio { + pub fn new(numerator: u32, denominator: u32) -> Self { + Self { + numerator, + denominator, + } + } + + pub fn new_int(numerator: u32) -> Self { + Self { + numerator, + denominator: 1, + } + } +} diff --git a/vm/src/types/instance_definitions/mod_instance_def.rs b/vm/src/types/instance_definitions/mod_instance_def.rs index 0b84077d33..72150b9c3b 100644 --- a/vm/src/types/instance_definitions/mod_instance_def.rs +++ b/vm/src/types/instance_definitions/mod_instance_def.rs @@ -1,12 +1,14 @@ use serde::Serialize; +use super::LowRatio; + pub(crate) const N_WORDS: usize = 4; pub(crate) const CELLS_PER_MOD: u32 = 7; #[derive(Serialize, Debug, PartialEq, Clone)] pub(crate) struct ModInstanceDef { - pub(crate) ratio: Option, + pub(crate) ratio: Option, pub(crate) word_bit_len: u32, pub(crate) batch_size: usize, } @@ -14,9 +16,28 @@ pub(crate) struct ModInstanceDef { impl ModInstanceDef { pub(crate) fn new(ratio: Option, batch_size: usize, word_bit_len: u32) -> Self { ModInstanceDef { - ratio, + ratio: ratio.map(LowRatio::new_int), word_bit_len, batch_size, } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::*; + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_new() { + let builtin_instance = ModInstanceDef { + ratio: Some(LowRatio::new_int(10)), + word_bit_len: 3, + batch_size: 3, + }; + assert_eq!(ModInstanceDef::new(Some(10), 3, 3), builtin_instance); + } +} diff --git a/vm/src/types/instance_definitions/range_check_instance_def.rs b/vm/src/types/instance_definitions/range_check_instance_def.rs index 4524fca9bb..ed09d7cfb3 100644 --- a/vm/src/types/instance_definitions/range_check_instance_def.rs +++ b/vm/src/types/instance_definitions/range_check_instance_def.rs @@ -1,20 +1,26 @@ use serde::Serialize; + +use super::LowRatio; pub(crate) const CELLS_PER_RANGE_CHECK: u32 = 1; #[derive(Serialize, Debug, PartialEq)] pub(crate) struct RangeCheckInstanceDef { - pub(crate) ratio: Option, + pub(crate) ratio: Option, } impl Default for RangeCheckInstanceDef { fn default() -> Self { - RangeCheckInstanceDef { ratio: Some(8) } + RangeCheckInstanceDef { + ratio: Some(LowRatio::new(8, 1)), + } } } impl RangeCheckInstanceDef { pub(crate) fn new(ratio: Option) -> Self { - RangeCheckInstanceDef { ratio } + RangeCheckInstanceDef { + ratio: ratio.map(LowRatio::new_int), + } } } @@ -28,14 +34,18 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_new() { - let builtin_instance = RangeCheckInstanceDef { ratio: Some(10) }; + let builtin_instance = RangeCheckInstanceDef { + ratio: Some(LowRatio::new_int(10)), + }; assert_eq!(RangeCheckInstanceDef::new(Some(10)), builtin_instance); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_default() { - let builtin_instance = RangeCheckInstanceDef { ratio: Some(8) }; + let builtin_instance = RangeCheckInstanceDef { + ratio: Some(LowRatio::new_int(8)), + }; assert_eq!(RangeCheckInstanceDef::default(), builtin_instance); } } diff --git a/vm/src/types/layout.rs b/vm/src/types/layout.rs index b1f52e7698..58ccd8ef34 100644 --- a/vm/src/types/layout.rs +++ b/vm/src/types/layout.rs @@ -8,14 +8,17 @@ use super::{ }, }; -pub(crate) const MEMORY_UNITS_PER_STEP: u32 = 8; +pub(crate) const DEFAULT_MEMORY_UNITS_PER_STEP: u32 = 8; +pub(crate) const DEFAULT_CPU_COMPONENT_STEP: u32 = 1; use serde::{Deserialize, Deserializer, Serialize}; #[derive(Serialize, Debug)] pub struct CairoLayout { pub(crate) name: LayoutName, + pub(crate) cpu_component_step: u32, pub(crate) rc_units: u32, + pub(crate) memory_units_per_step: u32, pub(crate) builtins: BuiltinsInstanceDef, pub(crate) public_memory_fraction: u32, pub(crate) diluted_pool_instance_def: Option, @@ -26,6 +29,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::plain, rc_units: 16, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::plain(), public_memory_fraction: 4, diluted_pool_instance_def: None, @@ -36,6 +41,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::small, rc_units: 16, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::small(), public_memory_fraction: 4, diluted_pool_instance_def: None, @@ -46,6 +53,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::dex, rc_units: 4, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::dex(), public_memory_fraction: 4, diluted_pool_instance_def: None, @@ -56,6 +65,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::recursive, rc_units: 4, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::recursive(), public_memory_fraction: 8, diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()), @@ -66,6 +77,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::starknet, rc_units: 4, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::starknet(), public_memory_fraction: 8, diluted_pool_instance_def: Some(DilutedPoolInstanceDef::new(2, 4, 16)), @@ -76,6 +89,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::starknet_with_keccak, rc_units: 4, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::starknet_with_keccak(), public_memory_fraction: 8, diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()), @@ -86,6 +101,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::recursive_large_output, rc_units: 4, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::recursive_large_output(), public_memory_fraction: 8, diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()), @@ -95,6 +112,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::recursive_with_poseidon, rc_units: 4, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::recursive_with_poseidon(), public_memory_fraction: 8, diluted_pool_instance_def: Some(DilutedPoolInstanceDef::new(8, 4, 16)), @@ -105,6 +124,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::all_cairo, rc_units: 4, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::all_cairo(), public_memory_fraction: 8, diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()), @@ -115,6 +136,8 @@ impl CairoLayout { CairoLayout { name: LayoutName::all_solidity, rc_units: 8, + cpu_component_step: DEFAULT_CPU_COMPONENT_STEP, + memory_units_per_step: DEFAULT_MEMORY_UNITS_PER_STEP, builtins: BuiltinsInstanceDef::all_solidity(), public_memory_fraction: 8, diluted_pool_instance_def: Some(DilutedPoolInstanceDef::default()), @@ -125,11 +148,12 @@ impl CairoLayout { CairoLayout { name: LayoutName::dynamic, rc_units: params.rc_units, + cpu_component_step: params.cpu_component_step, + memory_units_per_step: params.memory_units_per_step, public_memory_fraction: 8, - diluted_pool_instance_def: Some(DilutedPoolInstanceDef { - units_per_step: 2_u32.pow(params.log_diluted_units_per_step), - ..DilutedPoolInstanceDef::default() - }), + diluted_pool_instance_def: Some(DilutedPoolInstanceDef::from_log_units_per_step( + params.log_diluted_units_per_step, + )), builtins: BuiltinsInstanceDef::dynamic(params), } } @@ -143,7 +167,9 @@ use arbitrary::{self, Arbitrary}; #[serde(try_from = "RawCairoLayoutParams")] pub struct CairoLayoutParams { pub rc_units: u32, - pub log_diluted_units_per_step: u32, + pub cpu_component_step: u32, + pub memory_units_per_step: u32, + pub log_diluted_units_per_step: i32, pub pedersen_ratio: u32, pub range_check_ratio: u32, pub ecdsa_ratio: u32, @@ -152,14 +178,11 @@ pub struct CairoLayoutParams { pub keccak_ratio: u32, pub poseidon_ratio: u32, pub range_check96_ratio: u32, + pub range_check96_ratio_den: u32, pub add_mod_ratio: u32, + pub add_mod_ratio_den: u32, pub mul_mod_ratio: u32, - // the following are not used right now - pub cpu_component_step: u32, - pub memory_units_per_step: u32, - pub range_check96_ratio_den: u32, pub mul_mod_ratio_den: u32, - pub add_mod_ratio_den: u32, } impl CairoLayoutParams { @@ -178,7 +201,9 @@ impl CairoLayoutParams { #[derive(Deserialize, Debug, Default, Clone)] pub struct RawCairoLayoutParams { pub rc_units: u32, - pub log_diluted_units_per_step: u32, + pub cpu_component_step: u32, + pub memory_units_per_step: u32, + pub log_diluted_units_per_step: i32, #[serde(deserialize_with = "bool_from_int_or_bool")] pub uses_pedersen_builtin: bool, pub pedersen_ratio: u32, @@ -203,18 +228,15 @@ pub struct RawCairoLayoutParams { #[serde(deserialize_with = "bool_from_int_or_bool")] pub uses_range_check96_builtin: bool, pub range_check96_ratio: u32, + pub range_check96_ratio_den: u32, #[serde(deserialize_with = "bool_from_int_or_bool")] pub uses_add_mod_builtin: bool, pub add_mod_ratio: u32, + pub add_mod_ratio_den: u32, #[serde(deserialize_with = "bool_from_int_or_bool")] pub uses_mul_mod_builtin: bool, pub mul_mod_ratio: u32, - // the following are not used right now - pub cpu_component_step: u32, - pub memory_units_per_step: u32, - pub range_check96_ratio_den: u32, pub mul_mod_ratio_den: u32, - pub add_mod_ratio_den: u32, } impl TryFrom for CairoLayoutParams { @@ -317,11 +339,12 @@ mod tests { use super::*; #[cfg(feature = "mod_builtin")] use crate::types::instance_definitions::mod_instance_def::ModInstanceDef; + use crate::types::instance_definitions::{ bitwise_instance_def::BitwiseInstanceDef, ec_op_instance_def::EcOpInstanceDef, ecdsa_instance_def::EcdsaInstanceDef, keccak_instance_def::KeccakInstanceDef, pedersen_instance_def::PedersenInstanceDef, poseidon_instance_def::PoseidonInstanceDef, - range_check_instance_def::RangeCheckInstanceDef, + range_check_instance_def::RangeCheckInstanceDef, LowRatio, }; #[cfg(target_arch = "wasm32")] @@ -452,6 +475,8 @@ mod tests { // dummy cairo layout params let params = CairoLayoutParams { rc_units: 32, + cpu_component_step: 8, + memory_units_per_step: 16, log_diluted_units_per_step: 5, pedersen_ratio: 32, range_check_ratio: 32, @@ -459,19 +484,21 @@ mod tests { bitwise_ratio: 32, ec_op_ratio: 32, keccak_ratio: 32, + poseidon_ratio: 0, + range_check96_ratio: 8, + range_check96_ratio_den: 16, + add_mod_ratio: 8, + add_mod_ratio_den: 16, mul_mod_ratio: 32, - ..Default::default() // - // cpu_component_step: todo!(), - // memory_units_per_step: todo!(), - // range_check96_ratio_den: todo!(), - // add_mod_ratio_den: todo!(), - // mul_mod_ratio_den: todo!(), + mul_mod_ratio_den: 16, }; let layout = CairoLayout::dynamic_instance(params); assert_eq!(layout.name, LayoutName::dynamic); assert_eq!(layout.rc_units, 32); + assert_eq!(layout.cpu_component_step, 8); + assert_eq!(layout.memory_units_per_step, 16); assert_eq!(layout.public_memory_fraction, 8); // hardcoded assert_eq!( layout.diluted_pool_instance_def, @@ -488,7 +515,9 @@ mod tests { ); assert_eq!( layout.builtins.range_check, - Some(RangeCheckInstanceDef { ratio: Some(32) }) + Some(RangeCheckInstanceDef { + ratio: Some(LowRatio::new_int(32)) + }) ); assert_eq!( layout.builtins.ecdsa, @@ -512,14 +541,19 @@ mod tests { ); assert_eq!( layout.builtins.range_check96, - Some(RangeCheckInstanceDef { ratio: Some(0) }) + Some(RangeCheckInstanceDef { + ratio: Some(LowRatio::new(8, 16)) + }) ); #[cfg(feature = "mod_builtin")] { assert_eq!( layout.builtins.mul_mod, Some(ModInstanceDef { - ratio: Some(32), + ratio: Some(LowRatio { + numerator: 32, + denominator: 16 + }), word_bit_len: 96, // hardcoded batch_size: 1 // hardcoded }), @@ -527,7 +561,10 @@ mod tests { assert_eq!( layout.builtins.add_mod, Some(ModInstanceDef { - ratio: Some(0), + ratio: Some(LowRatio { + numerator: 8, + denominator: 16 + }), word_bit_len: 96, // hardcoded batch_size: 1 // hardcoded }) diff --git a/vm/src/vm/runners/builtin_runner/mod.rs b/vm/src/vm/runners/builtin_runner/mod.rs index 26d4a9026c..2374f43f3d 100644 --- a/vm/src/vm/runners/builtin_runner/mod.rs +++ b/vm/src/vm/runners/builtin_runner/mod.rs @@ -47,7 +47,7 @@ pub use bitwise::BitwiseBuiltinRunner; pub use ec_op::EcOpBuiltinRunner; pub use hash::HashBuiltinRunner; pub use modulo::ModBuiltinRunner; -use num_integer::div_floor; +use num_integer::{div_ceil, div_floor}; pub use output::{OutputBuiltinRunner, OutputBuiltinState}; pub use poseidon::PoseidonBuiltinRunner; pub use range_check::RangeCheckBuiltinRunner; @@ -170,6 +170,14 @@ impl BuiltinRunner { pub fn get_allocated_memory_units( &self, vm: &VirtualMachine, + ) -> Result { + Ok(self.get_allocated_instances(vm)? * self.cells_per_instance() as usize) + } + + ///Returns the builtin's allocated instances + pub fn get_allocated_instances( + &self, + vm: &VirtualMachine, ) -> Result { match *self { BuiltinRunner::Output(_) | BuiltinRunner::SegmentArena(_) => Ok(0), @@ -179,23 +187,40 @@ impl BuiltinRunner { // Dynamic layout has the exact number of instances it needs (up to a power of 2). let instances: usize = self.get_used_cells(&vm.segments)? / self.cells_per_instance() as usize; - let components = (instances / self.instances_per_component() as usize) - .next_power_of_two(); - Ok(self.cells_per_instance() as usize - * self.instances_per_component() as usize - * components) + let needed_components = instances / self.instances_per_component() as usize; + + let components = if needed_components > 0 { + needed_components.next_power_of_two() + } else { + 0 + }; + Ok(self.instances_per_component() as usize * components) } + // Dynamic layout allows for builtins with ratio 0 + Some(0) => Ok(0), Some(ratio) => { - let min_step = (ratio * self.instances_per_component()) as usize; + let min_step_num = (ratio * self.instances_per_component()) as usize; + let min_step = if let Some(ratio_den) = self.ratio_den() { + div_ceil(min_step_num, ratio_den as usize) + } else { + min_step_num + }; + if vm.current_step < min_step { return Err(InsufficientAllocatedCellsError::MinStepNotReached( Box::new((min_step, self.name())), ) .into()); }; - let value = safe_div_usize(vm.current_step, ratio as usize) - .map_err(|_| MemoryError::ErrorCalculatingMemoryUnits)?; - Ok(self.cells_per_instance() as usize * value) + + let allocated_instances = if let Some(ratio_den) = self.ratio_den() { + safe_div_usize(vm.current_step * ratio_den as usize, ratio as usize) + .map_err(|_| MemoryError::ErrorCalculatingMemoryUnits)? + } else { + safe_div_usize(vm.current_step, ratio as usize) + .map_err(|_| MemoryError::ErrorCalculatingMemoryUnits)? + }; + Ok(allocated_instances) } } } @@ -252,6 +277,15 @@ impl BuiltinRunner { } } + pub fn ratio_den(&self) -> Option { + match self { + BuiltinRunner::RangeCheck(range_check) => range_check.ratio_den(), + BuiltinRunner::RangeCheck96(range_check) => range_check.ratio_den(), + BuiltinRunner::Mod(modulo) => modulo.ratio_den(), + _ => None, + } + } + pub fn add_validation_rule(&self, memory: &mut Memory) { match *self { BuiltinRunner::RangeCheck(ref range_check) => range_check.add_validation_rule(memory), @@ -662,6 +696,8 @@ mod tests { use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor; use crate::relocatable; use crate::types::builtin_name::BuiltinName; + use crate::types::instance_definitions::mod_instance_def::ModInstanceDef; + use crate::types::instance_definitions::LowRatio; use crate::types::program::Program; use crate::utils::test_utils::*; use crate::vm::errors::memory_errors::InsufficientAllocatedCellsError; @@ -1053,6 +1089,26 @@ mod tests { assert_eq!(builtin.get_allocated_memory_units(&vm), Ok(256)); } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_allocated_memory_units_zero_ratio() { + let builtin = BuiltinRunner::Keccak(KeccakBuiltinRunner::new(Some(0), true)); + let vm = vm!(); + assert_eq!(builtin.get_allocated_memory_units(&vm), Ok(0)); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_allocated_memory_units_none_ratio() { + let mut builtin = BuiltinRunner::Keccak(KeccakBuiltinRunner::new(None, true)); + let mut vm = vm!(); + + builtin.initialize_segments(&mut vm.segments); + vm.compute_segments_effective_sizes(); + + assert_eq!(builtin.get_allocated_memory_units(&vm), Ok(0)); + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_range_check_usage_range_check() { @@ -1543,6 +1599,30 @@ mod tests { assert_eq!(keccak_builtin.ratio(), (Some(2048)),); } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_ratio_den_tests() { + let rangecheck_builtin: BuiltinRunner = + RangeCheckBuiltinRunner::::new_with_low_ratio( + Some(LowRatio::new(1, 2)), + true, + ) + .into(); + assert_eq!(rangecheck_builtin.ratio_den(), (Some(2)),); + + let rangecheck96_builtin: BuiltinRunner = + RangeCheckBuiltinRunner::::new_with_low_ratio( + Some(LowRatio::new(1, 4)), + true, + ) + .into(); + assert_eq!(rangecheck96_builtin.ratio_den(), (Some(4)),); + + let mod_builtin: BuiltinRunner = + ModBuiltinRunner::new_add_mod(&ModInstanceDef::new(Some(5), 3, 3), true).into(); + assert_eq!(mod_builtin.ratio_den(), (Some(1)),); + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn bitwise_get_used_instances_test() { diff --git a/vm/src/vm/runners/builtin_runner/modulo.rs b/vm/src/vm/runners/builtin_runner/modulo.rs index 0f5bb7719b..3339c0b562 100644 --- a/vm/src/vm/runners/builtin_runner/modulo.rs +++ b/vm/src/vm/runners/builtin_runner/modulo.rs @@ -140,7 +140,11 @@ impl ModBuiltinRunner { } pub fn ratio(&self) -> Option { - self.instance_def.ratio + self.instance_def.ratio.map(|ratio| ratio.numerator) + } + + pub fn ratio_den(&self) -> Option { + self.instance_def.ratio.map(|ratio| ratio.denominator) } pub fn batch_size(&self) -> usize { diff --git a/vm/src/vm/runners/builtin_runner/range_check.rs b/vm/src/vm/runners/builtin_runner/range_check.rs index 9c19de3309..a4800bcf78 100644 --- a/vm/src/vm/runners/builtin_runner/range_check.rs +++ b/vm/src/vm/runners/builtin_runner/range_check.rs @@ -4,7 +4,7 @@ use crate::{ cmp::{max, min}, prelude::*, }, - types::builtin_name::BuiltinName, + types::{builtin_name::BuiltinName, instance_definitions::LowRatio}, }; use crate::Felt252; @@ -35,7 +35,7 @@ lazy_static! { #[derive(Debug, Clone)] pub struct RangeCheckBuiltinRunner { - ratio: Option, + ratio: Option, base: usize, pub(crate) stop_ptr: Option, pub(crate) included: bool, @@ -43,6 +43,18 @@ pub struct RangeCheckBuiltinRunner { impl RangeCheckBuiltinRunner { pub fn new(ratio: Option, included: bool) -> RangeCheckBuiltinRunner { + RangeCheckBuiltinRunner { + ratio: ratio.map(LowRatio::new_int), + base: 0, + stop_ptr: None, + included, + } + } + + pub fn new_with_low_ratio( + ratio: Option, + included: bool, + ) -> RangeCheckBuiltinRunner { RangeCheckBuiltinRunner { ratio, base: 0, @@ -68,7 +80,11 @@ impl RangeCheckBuiltinRunner { } pub fn ratio(&self) -> Option { - self.ratio + self.ratio.map(|ratio| ratio.numerator) + } + + pub fn ratio_den(&self) -> Option { + self.ratio.map(|ratio| ratio.denominator) } pub fn name(&self) -> BuiltinName { diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index a283885d57..239515458d 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -8,11 +8,7 @@ use crate::{ ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}, prelude::*, }, - types::{ - builtin_name::BuiltinName, - layout::{CairoLayoutParams, MEMORY_UNITS_PER_STEP}, - layout_name::LayoutName, - }, + types::{builtin_name::BuiltinName, layout::CairoLayoutParams, layout_name::LayoutName}, vm::{ runners::builtin_runner::SegmentArenaBuiltinRunner, trace::trace_entry::{relocate_trace_register, RelocatedTraceEntry}, @@ -308,7 +304,7 @@ impl CairoRunner { let included = program_builtins.remove(&BuiltinName::range_check); if included || self.is_proof_mode() { self.vm.builtin_runners.push( - RangeCheckBuiltinRunner::::new( + RangeCheckBuiltinRunner::::new_with_low_ratio( instance_def.ratio, included, ) @@ -366,8 +362,11 @@ impl CairoRunner { let included = program_builtins.remove(&BuiltinName::range_check96); if included || self.is_proof_mode() { self.vm.builtin_runners.push( - RangeCheckBuiltinRunner::::new(instance_def.ratio, included) - .into(), + RangeCheckBuiltinRunner::::new_with_low_ratio( + instance_def.ratio, + included, + ) + .into(), ); } } @@ -842,15 +841,20 @@ impl CairoRunner { diluted_pool_instance.n_bits, ); - let multiplier = safe_div_usize( - self.vm.current_step, - builtin_runner.ratio().unwrap_or(1) as usize, - )?; + let multiplier = builtin_runner.get_allocated_instances(&self.vm)?; used_units_by_builtins += used_units * multiplier; } - let diluted_units = diluted_pool_instance.units_per_step as usize * self.vm.current_step; + let diluted_units = if !diluted_pool_instance.fractional_units_per_step { + diluted_pool_instance.units_per_step as usize * self.vm.current_step + } else { + safe_div_usize( + self.vm.current_step, + diluted_pool_instance.units_per_step as usize, + )? + }; + let unused_diluted_units = diluted_units.saturating_sub(used_units_by_builtins); let diluted_usage_upper_bound = 1usize << diluted_pool_instance.n_bits; @@ -1178,7 +1182,7 @@ impl CairoRunner { // Out of the memory units available per step, a fraction is used for public memory, and // four are used for the instruction. - let total_memory_units = MEMORY_UNITS_PER_STEP * vm_current_step_u32; + let total_memory_units = instance.memory_units_per_step * vm_current_step_u32; let (public_memory_units, rem) = div_rem(total_memory_units, instance.public_memory_fraction); if rem != 0 { From d388218aa826acd871c72cec044010195f617514 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 21 Oct 2024 17:21:29 -0300 Subject: [PATCH 04/34] Update rust version (#1857) * update rust version * update rust version in CI * update Changelog --------- Co-authored-by: pefontana --- .github/workflows/bench.yml | 2 +- .github/workflows/cairo_1_programs.yml | 2 +- .github/workflows/fresh_run.yml | 6 +++--- .github/workflows/hint_accountant.yml | 2 +- .github/workflows/hyper_threading_benchmarks.yml | 2 +- .github/workflows/hyperfine.yml | 4 ++-- .github/workflows/iai_main.yml | 2 +- .github/workflows/iai_pr.yml | 4 ++-- .github/workflows/publish.yml | 2 +- .github/workflows/rust.yml | 12 ++++++------ CHANGELOG.md | 2 ++ README.md | 2 +- rust-toolchain | 2 +- 13 files changed, 23 insertions(+), 21 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 280f3b79ba..f428b7b096 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 with: components: rustfmt, clippy - uses: actions/checkout@v3 diff --git a/.github/workflows/cairo_1_programs.yml b/.github/workflows/cairo_1_programs.yml index aa7957cc58..420d325ee2 100644 --- a/.github/workflows/cairo_1_programs.yml +++ b/.github/workflows/cairo_1_programs.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 - name: Set up Cargo cache uses: Swatinem/rust-cache@v2 - name: Checkout diff --git a/.github/workflows/fresh_run.yml b/.github/workflows/fresh_run.yml index a09ffb4747..2cf3ec999d 100644 --- a/.github/workflows/fresh_run.yml +++ b/.github/workflows/fresh_run.yml @@ -33,12 +33,12 @@ jobs: sudo rm -rf /opt/ghc sudo rm -rf "/usr/local/share/boost" sudo rm -rf "$AGENT_TOOLSDIRECTORY" - + - name: Checkout uses: actions/checkout@v3 - + - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 - name: Install Pyenv uses: "gabrielfalcao/pyenv-action@v13" diff --git a/.github/workflows/hint_accountant.yml b/.github/workflows/hint_accountant.yml index 9d015e41d5..096256a169 100644 --- a/.github/workflows/hint_accountant.yml +++ b/.github/workflows/hint_accountant.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 - name: Set up Cargo cache uses: Swatinem/rust-cache@v2 - name: Checkout diff --git a/.github/workflows/hyper_threading_benchmarks.yml b/.github/workflows/hyper_threading_benchmarks.yml index d772a0a6e5..f24c0f26f4 100644 --- a/.github/workflows/hyper_threading_benchmarks.yml +++ b/.github/workflows/hyper_threading_benchmarks.yml @@ -26,7 +26,7 @@ jobs: sudo apt-get install -y hyperfine - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 with: components: rustfmt, clippy diff --git a/.github/workflows/hyperfine.yml b/.github/workflows/hyperfine.yml index f2fd0f8405..370d76d80a 100644 --- a/.github/workflows/hyperfine.yml +++ b/.github/workflows/hyperfine.yml @@ -67,14 +67,14 @@ jobs: steps: - name: Populate cache uses: actions/cache@v3 - id: cache + id: cache with: path: bin/cairo-vm-cli-${{ matrix.branch }} key: binary-${{ github.event.pull_request[matrix.branch].sha }} - name: Install Rust if: ${{ steps.cache.outputs.cache-hit != 'true' }} - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 - name: Checkout if: ${{ steps.cache.outputs.cache-hit != 'true' }} diff --git a/.github/workflows/iai_main.yml b/.github/workflows/iai_main.yml index 6177590fff..9545d7c1f6 100644 --- a/.github/workflows/iai_main.yml +++ b/.github/workflows/iai_main.yml @@ -11,7 +11,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 - name: Set up cargo cache uses: Swatinem/rust-cache@v2 - name: Python3 Build diff --git a/.github/workflows/iai_pr.yml b/.github/workflows/iai_pr.yml index 875643ea72..bfbd513f84 100644 --- a/.github/workflows/iai_pr.yml +++ b/.github/workflows/iai_pr.yml @@ -23,7 +23,7 @@ jobs: - name: Install Rust if: ${{ steps.cache-iai-results.outputs.cache-hit != 'true' }} - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 - name: Set up cargo cache if: ${{ steps.cache-iai-results.outputs.cache-hit != 'true' }} uses: Swatinem/rust-cache@v2 @@ -51,7 +51,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 - name: Set up cargo cache uses: Swatinem/rust-cache@v2 - name: Python3 Build diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 792a7535f2..0d85ed146c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,7 +13,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - name: Install stable toolchain - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 - name: Publish crate cairo-vm env: CRATES_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 18cdb5653d..13ecb59765 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -161,7 +161,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 with: components: rustfmt, clippy - name: Set up cargo cache @@ -201,7 +201,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 with: targets: wasm32-unknown-unknown @@ -247,7 +247,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 with: targets: wasm32-unknown-unknown @@ -287,7 +287,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 with: targets: wasm32-unknown-unknown @@ -329,7 +329,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 with: components: llvm-tools-preview - name: Set up cargo cache @@ -395,7 +395,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install Rust - uses: dtolnay/rust-toolchain@1.80.0 + uses: dtolnay/rust-toolchain@1.81.0 - name: Set up cargo cache uses: Swatinem/rust-cache@v2 - name: Checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e19803711..3ddef6292a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* chore: update Rust required version to 1.81.0 [#1857](https://github.com/lambdaclass/cairo-vm/pull/1857) + * feat(BREAKING): [#1824](https://github.com/lambdaclass/cairo-vm/pull/1824)[#1838](https://github.com/lambdaclass/cairo-vm/pull/1838): * Add support for dynamic layout * CLI change(BREAKING): The flag `cairo_layout_params_file` must be specified when using dynamic layout. diff --git a/README.md b/README.md index ffae28ccdf..5056118793 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ It's Turing-complete and it was created by [Starkware](https://starkware.co/) as These are needed in order to compile and use the project. -- [Rust 1.80.0 or newer](https://www.rust-lang.org/tools/install) +- [Rust 1.81.0 or newer](https://www.rust-lang.org/tools/install) - Cargo #### Optional diff --git a/rust-toolchain b/rust-toolchain index ff6d7a9a85..5988090d17 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "1.80.0" +channel = "1.81.0" components = ["rustfmt", "clippy"] profile = "minimal" From efecd4f62a8317b5297ddccb9c86aa90d21f3959 Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 21 Oct 2024 18:17:10 -0300 Subject: [PATCH 05/34] Update cairo-lang deps to v2.9.0 dev.0 (#1858) * update rust version * update rust version in CI * update cairo-lang version to 2.9.0-dev.0 * update Changelog * update Changelog --------- Co-authored-by: pefontana --- CHANGELOG.md | 2 + Cargo.lock | 107 +++++++++++++++++++++--------------------- Cargo.toml | 16 +++---- Makefile | 2 +- cairo1-run/Cargo.toml | 6 +-- cairo1-run/Makefile | 2 +- 6 files changed, 69 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ddef6292a..dcc3f35982 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* chore: bump `cairo-lang-` dependencies to 2.9.0-dev.0 [#1858](https://github.com/lambdaclass/cairo-vm/pull/1858/files) + * chore: update Rust required version to 1.81.0 [#1857](https://github.com/lambdaclass/cairo-vm/pull/1857) * feat(BREAKING): [#1824](https://github.com/lambdaclass/cairo-vm/pull/1824)[#1838](https://github.com/lambdaclass/cairo-vm/pull/1838): diff --git a/Cargo.lock b/Cargo.lock index 03c0cb9c47..77a47fe913 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -437,9 +437,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cairo-lang-casm" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9e8fe95ee2add1537d00467b98bb8928334633eb01dcba7f33fb64769af259" +checksum = "e1e0dcdb6358bb639dd729546611bd99bada94c86e3f262c3637855abea9a972" dependencies = [ "cairo-lang-utils", "indoc", @@ -451,9 +451,9 @@ dependencies = [ [[package]] name = "cairo-lang-compiler" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0db1ae47b4918a894b60160fac42e6fbcb5a8c0023dd6c290ba03a1bcdf5a554" +checksum = "b8657f5a5611f341a85e80ba0b21848fc34bfdf391bfd93df0baf4516c3e4159" dependencies = [ "anyhow", "cairo-lang-defs", @@ -477,18 +477,18 @@ dependencies = [ [[package]] name = "cairo-lang-debug" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c87b905b74516c33fc7e6d61b5243363ce65133054c30bd9531f47e30ca201" +checksum = "0635aa554d297acefe6a35b495aba2795d0af5b7f97c4ab63829c7d62291ef41" dependencies = [ "cairo-lang-utils", ] [[package]] name = "cairo-lang-defs" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611996d85ec608bfec75d546a5c2ec44f664f4bd2514840a5b369d30a1a8bfdb" +checksum = "86b356e1c09898e8b8cfdd9731579d89365a13d8b4f7e717962e0cc7d125b83c" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -503,9 +503,9 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d015a0790b1f5de8b22b4b4b60d392c35bed07b7aa9dd22361af2793835cee51" +checksum = "2dfe7c6ff96182da29012b707a3554e34a50f19cc96013ee45b0eb36dd396ec8" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -515,9 +515,9 @@ dependencies = [ [[package]] name = "cairo-lang-eq-solver" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c580e56e5857d51b6bf2ec5ed5fdd33fd3b74dad7e3cb6d7398396174a6c85" +checksum = "723d244465309d5409e297b5486d62cbec06f2c47b05044414bb640e3f14caab" dependencies = [ "cairo-lang-utils", "good_lp", @@ -525,9 +525,9 @@ dependencies = [ [[package]] name = "cairo-lang-filesystem" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5368e66a742b8532d656171525bfea599490280ceee10bdac93ad60775fc4e59" +checksum = "237030772ae5368f19a9247e1f63f753f8ad8de963477166e402f4825c0a141d" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -536,13 +536,14 @@ dependencies = [ "semver", "serde", "smol_str", + "toml", ] [[package]] name = "cairo-lang-formatter" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1200324728e7f4c4acedceee427d9b3ffce221af57e469a454f007cbc248255" +checksum = "5b71f0eb3a36a6cb5f7f07843926783c4c17e44c9516b53171727a108782f3eb" dependencies = [ "anyhow", "cairo-lang-diagnostics", @@ -555,15 +556,14 @@ dependencies = [ "itertools 0.12.1", "rust-analyzer-salsa", "serde", - "smol_str", "thiserror", ] [[package]] name = "cairo-lang-lowering" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a7a3069c75e1aca7cf15f20d03baf71f5c86e5be26988f6c25656549aa8b54a" +checksum = "7d095d78e2f1de499429c95655d6135a3d24c384b36d8de9f84e0aa4e07ee152" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -578,6 +578,7 @@ dependencies = [ "itertools 0.12.1", "log", "num-bigint", + "num-integer", "num-traits 0.2.19", "rust-analyzer-salsa", "smol_str", @@ -585,9 +586,9 @@ dependencies = [ [[package]] name = "cairo-lang-parser" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13b245ddc740ebfed8b05e1bdb7805a06d267cf89d46486c9609306f92d45ce" +checksum = "bb828af7f948a3ef7fa65de14e3f639daedefb046dfefcad6e3116d2cb0f89a0" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -605,9 +606,9 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b656552d0ab4a69be223e42c4e1c4028e512f506a237d04bbe4ccab9a1e13c5" +checksum = "135a600043bf7030eacc6ebf2a609c2364d6ffeb04e1f3c809a2738f6b02c829" dependencies = [ "cairo-lang-defs", "cairo-lang-diagnostics", @@ -624,9 +625,9 @@ dependencies = [ [[package]] name = "cairo-lang-proc-macros" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05cc6adb49faa42ea825e041dff0496c2e72e4ddaf50734062a62383c0c8adbf" +checksum = "ac857ec4b564712f3e16e3314e23cc0787ab1c05cdfee83f1c8f9989a6eee40f" dependencies = [ "cairo-lang-debug", "quote", @@ -635,9 +636,9 @@ dependencies = [ [[package]] name = "cairo-lang-project" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad123ba0e0dd5e1ea80977c0244ff4b0b6d8bf050d42ecb5ff0cf7f885e871f9" +checksum = "23cc37b7f8889cdea631aeea3bcc70d5c86ac8fb1d98aabc83f16283d60f1643" dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", @@ -649,9 +650,9 @@ dependencies = [ [[package]] name = "cairo-lang-semantic" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d528c79e4ff3e1364569c07e22660ddf60c0d1989705b8f0feed9949962b28a" +checksum = "c560cf4b4a89325d3a9594f490fffee38cf30e0990e808bb927619de9d0c973a" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -675,9 +676,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bdb0c2cc419f45ab7e413322502ca02c2a2c56aeabdd0885e3740f378d8b269" +checksum = "8118f55ca7d567bfc60960b445d388564d04bf48335c983b1595cb35f67a01c5" dependencies = [ "anyhow", "cairo-lang-utils", @@ -702,9 +703,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7224cd827ccf69e742c90a60278876865a96b545a101248d9472d2e02f9190b3" +checksum = "2716ef8d4ce0fb700f83ed3281f3656436570e60249d41c65c79dc1ca27be002" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -718,9 +719,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-gas" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e379e3010827fe983e66aa38a0d25fe24cfc11eaf8cadf4dc7bcb31fff031de" +checksum = "24a44da87a35845470c4f4c648225232a15e0875fe809045b6088464491f838b" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -734,9 +735,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-generator" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b353930676c06bb885a16ec3b120109aa15539c49f41b3370a5a6314dc29dc" +checksum = "15bc5cf9f3965a7030a114dfe3d31d183287fbfbfbf904deaaa2468cadb936aa" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -758,9 +759,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83873751d489aae4674f3d755a4897429a664bdc4b0847283e13889f0b0c2a44" +checksum = "18b7616f1a3c41c4646094b5abf774e558428e9c1eda5d78d7b0638ec5c264e5" dependencies = [ "assert_matches", "cairo-lang-casm", @@ -779,9 +780,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-type-size" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd84b445715326e44832836732b6bda76a119116b296ac9b6b87e2a4177634a" +checksum = "871077dbc08df5d134dc3975538171c14b266ba405d1298085afdb227216f0a3" dependencies = [ "cairo-lang-sierra", "cairo-lang-utils", @@ -789,9 +790,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8df3086f909d27a49d6706be835725df4e21fb50efe699cd763d1f782a31dea" +checksum = "9f21804eb8931d41e258e7a393afc8ee8858308e95b3ed2e9b6b469ef68a6a50" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -819,9 +820,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet-classes" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41bcab650779b3431389dc52f1e643a7c9690a1aa2b072c8f01955503d094007" +checksum = "b2496bccd68fa0286b35b72c98439316a3a872ef7ec6d881f0dac90b17997490" dependencies = [ "cairo-lang-casm", "cairo-lang-sierra", @@ -842,9 +843,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e2dc876ec02a197b8d13dbfc0b2cf7a7e31dcfc6446761cbb85f5b42d589cdc" +checksum = "8d77ea2e35d3610098ff13e373fc519aedc6a5096ed8547081aacfc104ef4422" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -858,9 +859,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8727fe3f24ec0834ec6656c70a59f85233439f0a09ca53cf5e27fbdb1b40193" +checksum = "6b01d505ab26ca9ce829faf3a8dd097f5d7962d2eb8f136017a260694a6a72e8" dependencies = [ "genco", "xshell", @@ -868,9 +869,9 @@ dependencies = [ [[package]] name = "cairo-lang-test-utils" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a7681562268173d74b1c8d2438a1d9ec3218c89a8e39a8be3f10e044fa46ebe" +checksum = "eb143a22f5a3510df8c4dec76e17c1e36bbcbddcd7915601f6a51a72418c454f" dependencies = [ "cairo-lang-formatter", "cairo-lang-utils", @@ -881,9 +882,9 @@ dependencies = [ [[package]] name = "cairo-lang-utils" -version = "2.8.0" +version = "2.9.0-dev.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e6004780c42bf28ce5afd048cc628b3de34aaf24fd2c228ae73217c58999f9" +checksum = "35df943ebcf8e1db11ee9f4f46f843dde5b71639ca79ea0d8caa7973f91d8b12" dependencies = [ "hashbrown 0.14.5", "indexmap 2.5.0", diff --git a/Cargo.toml b/Cargo.toml index 64a4af3e09..eda925bef9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,15 +62,15 @@ thiserror-no-std = { version = "2.0.2", default-features = false } bitvec = { version = "1", default-features = false, features = ["alloc"] } # Dependencies for cairo-1-hints feature -cairo-lang-starknet = { version = "2.8.0", default-features = false } -cairo-lang-casm = { version = "2.8.0", default-features = false } +cairo-lang-starknet = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-casm = { version = "2.9.0-dev.0", default-features = false } -cairo-lang-starknet-classes = { version = "2.8.0", default-features = false } -cairo-lang-compiler = { version = "=2.8.0", default-features = false } -cairo-lang-sierra-to-casm = { version = "2.8.0", default-features = false } -cairo-lang-sierra = { version = "2.8.0", default-features = false } -cairo-lang-runner = { version = "2.8.0", default-features = false } -cairo-lang-utils = { version = "=2.8.0", default-features = false } +cairo-lang-starknet-classes = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-compiler = { version = "=2.9.0-dev.0", default-features = false } +cairo-lang-sierra-to-casm = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-sierra = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-runner = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-utils = { version = "=2.9.0-dev.0", default-features = false } # TODO: check these dependencies for wasm compatibility ark-ff = { version = "0.4.2", default-features = false } diff --git a/Makefile b/Makefile index 06cba4b0f1..49183fd314 100644 --- a/Makefile +++ b/Makefile @@ -180,7 +180,7 @@ $(CAIRO_2_CONTRACTS_TEST_DIR)/%.casm: $(CAIRO_2_CONTRACTS_TEST_DIR)/%.sierra # ====================== CAIRO_2_REPO_DIR = cairo2 -CAIRO_2_VERSION = 2.8.0 +CAIRO_2_VERSION = 2.9.0-dev.0 build-cairo-2-compiler-macos: @if [ ! -d "$(CAIRO_2_REPO_DIR)" ]; then \ diff --git a/cairo1-run/Cargo.toml b/cairo1-run/Cargo.toml index 500d410d28..45944c55da 100644 --- a/cairo1-run/Cargo.toml +++ b/cairo1-run/Cargo.toml @@ -12,9 +12,9 @@ keywords.workspace = true cairo-vm = { workspace = true, features = ["std", "cairo-1-hints", "clap"] } serde_json = { workspace = true } -cairo-lang-sierra-type-size = { version = "2.8.0", default-features = false } -cairo-lang-sierra-ap-change = { version = "2.8.0", default-features = false } -cairo-lang-sierra-gas = { version = "2.8.0", default-features = false } +cairo-lang-sierra-type-size = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-sierra-ap-change = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-sierra-gas = { version = "2.9.0-dev.0", default-features = false } cairo-lang-starknet-classes.workspace = true cairo-lang-sierra-to-casm.workspace = true cairo-lang-compiler.workspace = true diff --git a/cairo1-run/Makefile b/cairo1-run/Makefile index a00f9dfe3f..238b2fea72 100644 --- a/cairo1-run/Makefile +++ b/cairo1-run/Makefile @@ -13,7 +13,7 @@ TRACES:=$(patsubst $(CAIRO_1_FOLDER)/%.cairo, $(CAIRO_1_FOLDER)/%.trace, $(CAIRO MEMORY:=$(patsubst $(CAIRO_1_FOLDER)/%.cairo, $(CAIRO_1_FOLDER)/%.memory, $(CAIRO_1_PROGRAMS)) deps: - git clone --depth=1 -b v2.8.0 https://github.com/starkware-libs/cairo.git \ + git clone --depth=1 -b v2.9.0-dev.0 https://github.com/starkware-libs/cairo.git \ && mv cairo/corelib/ . \ && rm -rf cairo/ From d2257d659e20f7c38ff6c35086bd031620c4ca6c Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Wed, 23 Oct 2024 11:12:19 -0300 Subject: [PATCH 06/34] release-v2.0.0-rc0 (#1859) Co-authored-by: pefontana --- CHANGELOG.md | 2 ++ Cargo.lock | 14 +++++++------- Cargo.toml | 6 +++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcc3f35982..1595eb1efc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +#### [2.0.0-rc0] - 2024-10-22 + * chore: bump `cairo-lang-` dependencies to 2.9.0-dev.0 [#1858](https://github.com/lambdaclass/cairo-vm/pull/1858/files) * chore: update Rust required version to 1.81.0 [#1857](https://github.com/lambdaclass/cairo-vm/pull/1857) diff --git a/Cargo.lock b/Cargo.lock index 77a47fe913..4aef2cd4c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -897,7 +897,7 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "1.0.1" +version = "2.0.0-rc0" dependencies = [ "anyhow", "arbitrary", @@ -941,7 +941,7 @@ dependencies = [ [[package]] name = "cairo-vm-cli" -version = "1.0.1" +version = "2.0.0-rc0" dependencies = [ "assert_matches", "bincode", @@ -956,7 +956,7 @@ dependencies = [ [[package]] name = "cairo-vm-tracer" -version = "1.0.1" +version = "2.0.0-rc0" dependencies = [ "axum", "cairo-vm", @@ -975,7 +975,7 @@ dependencies = [ [[package]] name = "cairo1-run" -version = "1.0.1" +version = "2.0.0-rc0" dependencies = [ "assert_matches", "bincode", @@ -1633,7 +1633,7 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hint_accountant" -version = "1.0.1" +version = "2.0.0-rc0" dependencies = [ "cairo-vm", "serde", @@ -1714,7 +1714,7 @@ dependencies = [ [[package]] name = "hyper_threading" -version = "1.0.1" +version = "2.0.0-rc0" dependencies = [ "cairo-vm", "rayon", @@ -3611,7 +3611,7 @@ dependencies = [ [[package]] name = "wasm-demo" -version = "1.0.1" +version = "2.0.0-rc0" dependencies = [ "cairo-vm", "console_error_panic_hook", diff --git a/Cargo.toml b/Cargo.toml index eda925bef9..7338b83ee0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ exclude = ["ensure-no_std"] resolver = "2" [workspace.package] -version = "1.0.1" +version = "2.0.0-rc0" edition = "2021" license = "Apache-2.0" repository = "https://github.com/lambdaclass/cairo-vm/" @@ -24,8 +24,8 @@ readme = "README.md" keywords = ["starknet", "cairo", "vm", "wasm", "no_std"] [workspace.dependencies] -cairo-vm = { path = "./vm", version = "1.0.1", default-features = false } -cairo-vm-tracer = { path = "./cairo-vm-tracer", version = "1.0.1", default-features = false } +cairo-vm = { path = "./vm", version = "2.0.0-rc0", default-features = false } +cairo-vm-tracer = { path = "./cairo-vm-tracer", version = "2.0.0-rc0", default-features = false } mimalloc = { version = "0.1.37", default-features = false } num-bigint = { version = "0.4", default-features = false, features = [ "serde", From 159f67da19964cc54a95423a69470a26e534a13d Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Wed, 23 Oct 2024 17:34:30 -0300 Subject: [PATCH 07/34] Update docs, cairo-lang-runner references (#1854) * Update docs * Fix typo * update * update dict docs --------- Co-authored-by: pefontana --- cairo1-run/src/cairo_run.rs | 8 ++++++++ .../hint_processor/cairo_1_hint_processor/dict_manager.rs | 3 +++ .../cairo_1_hint_processor/hint_processor.rs | 4 +++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index bf654e9724..f22a6edd9a 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -366,6 +366,8 @@ fn build_hints_vec<'b>( (hints, program_hints) } +// Function derived from the cairo-lang-runner crate. +// https://github.com/starkware-libs/cairo/blob/40a7b60687682238f7f71ef7c59c986cc5733915/crates/cairo-lang-runner/src/lib.rs#L551-L552 /// Finds first function ending with `name_suffix`. fn find_function<'a>( sierra_program: &'a SierraProgram, @@ -384,6 +386,8 @@ fn find_function<'a>( .ok_or_else(|| RunnerError::MissingMain) } +// Function derived from the cairo-lang-runner crate. +// https://github.com/starkware-libs/cairo/blob/40a7b60687682238f7f71ef7c59c986cc5733915/crates/cairo-lang-runner/src/lib.rs#L750 /// Creates a list of instructions that will be appended to the program's bytecode. fn create_code_footer() -> Vec { casm! { @@ -527,6 +531,8 @@ fn load_arguments( Ok(()) } +// Function derived from the cairo-lang-runner crate. +// https://github.com/starkware-libs/cairo/blob/40a7b60687682238f7f71ef7c59c986cc5733915/crates/cairo-lang-runner/src/lib.rs#L703 /// Returns the instructions to add to the beginning of the code to successfully call the main /// function, as well as the builtins required to execute the program. fn create_entry_code( @@ -869,6 +875,8 @@ fn create_entry_code( )) } +// Function derived from the cairo-lang-runner crate. +// https://github.com/starkware-libs/cairo/blob/40a7b60687682238f7f71ef7c59c986cc5733915/crates/cairo-lang-runner/src/lib.rs#L577 fn get_info<'a>( sierra_program_registry: &'a ProgramRegistry, ty: &'a cairo_lang_sierra::ids::ConcreteTypeId, diff --git a/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs b/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs index b95c0b5232..a82a4fa2db 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs @@ -1,3 +1,6 @@ +// Most of the structs and implementations of these Dictionaries are based on the `cairo-lang-runner` crate. +// Reference: https://github.com/starkware-libs/cairo/blob/main/crates/cairo-lang-runner/src/casm_run/dict_manager.rs + use num_traits::One; use crate::stdlib::collections::HashMap; diff --git a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs index 98bb0a1547..0caf9c4e9c 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs @@ -71,7 +71,9 @@ impl Cairo1HintProcessor { segment_arena_validations, } } - // Runs a single Hint + // Most of the Hints implementations are derived from the `cairo-lang-runner` crate. + // https://github.com/starkware-libs/cairo/blob/40a7b60687682238f7f71ef7c59c986cc5733915/crates/cairo-lang-runner/src/casm_run/mod.rs#L1681 + /// Runs a single Hint pub fn execute( &self, vm: &mut VirtualMachine, From 39ad790554b50811eec0a236abf4db356fd69956 Mon Sep 17 00:00:00 2001 From: YairVaknin-starkware <141148375+YairVaknin-starkware@users.noreply.github.com> Date: Wed, 6 Nov 2024 00:30:34 +0200 Subject: [PATCH 08/34] Skip_pedersen_comparison_when_checking_pie_compatibility (#1855) Co-authored-by: Pedro Fontana --- CHANGELOG.md | 2 ++ vm/src/vm/runners/cairo_pie.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1595eb1efc..806d9da4d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## Cairo-VM Changelog #### Upcoming Changes +* fix: [#1855](https://github.com/lambdaclass/cairo-vm/pull/1855): + * Adds logic to skip pedersen additional data comparison when checking pie compatibility. #### [2.0.0-rc0] - 2024-10-22 diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index d86b1840c8..766d392899 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -289,6 +289,10 @@ impl CairoPie { return Err(CairoPieValidationError::DiffAdditionalData); } for (name, data) in self.additional_data.0.iter() { + // As documented above, we skip the pedersen field when comparing. + if *name == BuiltinName::pedersen { + continue; + } if !pie.additional_data.0.get(name).is_some_and(|d| d == data) { return Err(CairoPieValidationError::DiffAdditionalDataForBuiltin(*name)); } From 84e513df69255177eaeb5254b1b895608ec18bb4 Mon Sep 17 00:00:00 2001 From: Michael Zaikin Date: Wed, 6 Nov 2024 17:40:34 +0000 Subject: [PATCH 09/34] Runner: use CairoProgram::assemble_ex for producing bytecode, which includes constants data (#1864) Co-authored-by: Pedro Fontana --- CHANGELOG.md | 3 +++ cairo1-run/src/cairo_run.rs | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 806d9da4d6..9c3abb2a6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ #### [2.0.0-rc0] - 2024-10-22 +* fix: [#1864](https://github.com/lambdaclass/cairo-vm/pull/1864): + * Runner: include data from constants segment to the bytecode when assembling program + * chore: bump `cairo-lang-` dependencies to 2.9.0-dev.0 [#1858](https://github.com/lambdaclass/cairo-vm/pull/1858/files) * chore: update Rust required version to 1.81.0 [#1857](https://github.com/lambdaclass/cairo-vm/pull/1857) diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index f22a6edd9a..8a293c680e 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -204,10 +204,14 @@ pub fn cairo_run_program( cairo_run_config.copy_to_output(), ); - let data: Vec = instructions - .flat_map(|inst| inst.assemble().encode()) - .map(|x| Felt252::from(&x)) - .map(MaybeRelocatable::from) + // The bytecode includes all program instructions plus entry/footer, + // plus data from the constants segments. + let data: Vec = casm_program + .assemble_ex(&entry_code.instructions, &libfunc_footer) + .bytecode + .into_iter() + .map(Into::::into) + .map(Into::::into) .collect(); let program = if cairo_run_config.proof_mode { From e5c079cb998bc9e6e0ceb94d251df1069c6c2a6e Mon Sep 17 00:00:00 2001 From: YairVaknin-starkware <141148375+YairVaknin-starkware@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:14:53 +0200 Subject: [PATCH 10/34] Add_missing_builtins_to_pie_metadata_serialiazation (#1868) Co-authored-by: Pedro Fontana --- CHANGELOG.md | 3 +++ vm/src/vm/runners/cairo_pie.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c3abb2a6a..f81b7f66e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## Cairo-VM Changelog #### Upcoming Changes +* fix: [#1868](https://github.com/lambdaclass/cairo-vm/pull/1855): + * Adds logic to include the 3 new builtins in `builtin_segments` when serializing the output cairo pie's metadata. + * fix: [#1855](https://github.com/lambdaclass/cairo-vm/pull/1855): * Adds logic to skip pedersen additional data comparison when checking pie compatibility. diff --git a/vm/src/vm/runners/cairo_pie.rs b/vm/src/vm/runners/cairo_pie.rs index 766d392899..4383671971 100644 --- a/vm/src/vm/runners/cairo_pie.rs +++ b/vm/src/vm/runners/cairo_pie.rs @@ -763,6 +763,9 @@ pub(super) mod serde_impl { BuiltinName::ec_op, BuiltinName::keccak, BuiltinName::poseidon, + BuiltinName::range_check96, + BuiltinName::add_mod, + BuiltinName::mul_mod, ]; for name in BUILTIN_ORDERED_LIST { From 60252573255bdf77cf980d689db5b8539dde5e52 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Wed, 6 Nov 2024 22:37:46 +0100 Subject: [PATCH 11/34] serde: add `size` field to `Identifier` (#1861) * serde: add size field to Identifier * fix changelog --------- Co-authored-by: Pedro Fontana --- CHANGELOG.md | 2 ++ vm/src/serde/deserialize_program.rs | 24 ++++++++++++++++-------- vm/src/serde/serialize_program.rs | 3 +++ vm/src/types/program.rs | 20 ++++++++++++++++++++ vm/src/vm/runners/cairo_runner.rs | 4 ++++ 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f81b7f66e8..d4f8d6d455 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * fix: [#1855](https://github.com/lambdaclass/cairo-vm/pull/1855): * Adds logic to skip pedersen additional data comparison when checking pie compatibility. +* serde: add `size` field to `Identifier` [#1861]https://github.com/lambdaclass/cairo-vm/pull/1861 + #### [2.0.0-rc0] - 2024-10-22 * fix: [#1864](https://github.com/lambdaclass/cairo-vm/pull/1864): diff --git a/vm/src/serde/deserialize_program.rs b/vm/src/serde/deserialize_program.rs index 3fbd848932..052d9ae09c 100644 --- a/vm/src/serde/deserialize_program.rs +++ b/vm/src/serde/deserialize_program.rs @@ -102,6 +102,7 @@ pub struct Identifier { pub full_name: Option, pub members: Option>, pub cairo_type: Option, + pub size: Option, } #[cfg_attr(feature = "test_utils", derive(Arbitrary))] @@ -566,7 +567,7 @@ mod tests { "attributes": [], "debug_info": { "instruction_locations": {} - }, + }, "builtins": [], "data": [ "0x480680017fff8000", @@ -1012,6 +1013,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); identifiers.insert( @@ -1025,6 +1027,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); identifiers.insert( @@ -1036,6 +1039,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); identifiers.insert( @@ -1049,6 +1053,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); identifiers.insert( @@ -1060,6 +1065,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); identifiers.insert( @@ -1071,6 +1077,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); identifiers.insert( @@ -1082,6 +1089,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -1097,7 +1105,7 @@ mod tests { "attributes": [], "debug_info": { "instruction_locations": {} - }, + }, "builtins": [], "data": [ ], @@ -1178,10 +1186,10 @@ mod tests { "start_pc": 402, "value": "SafeUint256: subtraction overflow" } - ], + ], "debug_info": { "instruction_locations": {} - }, + }, "builtins": [], "data": [ ], @@ -1235,7 +1243,7 @@ mod tests { let valid_json = r#" { "prime": "0x800000000000011000000000000000000000000000000000000000000000001", - "attributes": [], + "attributes": [], "debug_info": { "file_contents": {}, "instruction_locations": { @@ -1286,7 +1294,7 @@ mod tests { } } } - }, + }, "builtins": [], "data": [ ], @@ -1344,7 +1352,7 @@ mod tests { let valid_json = r#" { "prime": "0x800000000000011000000000000000000000000000000000000000000000001", - "attributes": [], + "attributes": [], "debug_info": { "file_contents": {}, "instruction_locations": { @@ -1391,7 +1399,7 @@ mod tests { } } } - }, + }, "builtins": [], "data": [ ], diff --git a/vm/src/serde/serialize_program.rs b/vm/src/serde/serialize_program.rs index f8bd0d076a..1e9f83e8d1 100644 --- a/vm/src/serde/serialize_program.rs +++ b/vm/src/serde/serialize_program.rs @@ -127,6 +127,7 @@ pub(crate) struct IdentifierSerializer { pub full_name: Option, pub members: Option>, pub cairo_type: Option, + pub size: Option, } impl From for Identifier { @@ -138,6 +139,7 @@ impl From for Identifier { full_name: identifier_serialer.full_name, members: identifier_serialer.members, cairo_type: identifier_serialer.cairo_type, + size: identifier_serialer.size, } } } @@ -151,6 +153,7 @@ impl From for IdentifierSerializer { full_name: identifier_serialer.full_name, members: identifier_serialer.members, cairo_type: identifier_serialer.cairo_type, + size: identifier_serialer.size, } } } diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index 0fc8c6dc83..477f996577 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -720,6 +720,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -732,6 +733,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -773,6 +775,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -785,6 +788,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -934,6 +938,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -946,6 +951,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -1059,6 +1065,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -1071,6 +1078,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -1123,6 +1131,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -1135,6 +1144,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -1182,6 +1192,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); identifiers.insert( @@ -1193,6 +1204,7 @@ mod tests { full_name: Some("__main__.main.Args".to_string()), members: Some(HashMap::new()), cairo_type: None, + size: Some(0), }, ); identifiers.insert( @@ -1204,6 +1216,7 @@ mod tests { full_name: Some("__main__.main.ImplicitArgs".to_string()), members: Some(HashMap::new()), cairo_type: None, + size: Some(0), }, ); identifiers.insert( @@ -1215,6 +1228,7 @@ mod tests { full_name: Some("__main__.main.Return".to_string()), members: Some(HashMap::new()), cairo_type: None, + size: Some(0), }, ); identifiers.insert( @@ -1226,6 +1240,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); @@ -1281,6 +1296,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); identifiers.insert( @@ -1292,6 +1308,7 @@ mod tests { full_name: Some("__main__.main.Args".to_string()), members: Some(HashMap::new()), cairo_type: None, + size: Some(0), }, ); identifiers.insert( @@ -1303,6 +1320,7 @@ mod tests { full_name: Some("__main__.main.ImplicitArgs".to_string()), members: Some(HashMap::new()), cairo_type: None, + size: Some(0), }, ); identifiers.insert( @@ -1314,6 +1332,7 @@ mod tests { full_name: Some("__main__.main.Return".to_string()), members: Some(HashMap::new()), cairo_type: None, + size: Some(0), }, ); identifiers.insert( @@ -1325,6 +1344,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ); diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 239515458d..65209c35de 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -4489,6 +4489,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, )] .into_iter() @@ -4517,6 +4518,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ), ( @@ -4528,6 +4530,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, ), ] @@ -4557,6 +4560,7 @@ mod tests { full_name: None, members: None, cairo_type: None, + size: None, }, )] .into_iter() From 4bd5794c3fd67fd3e34db6d07b46975a08651052 Mon Sep 17 00:00:00 2001 From: YairVaknin-starkware <141148375+YairVaknin-starkware@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:28:35 +0200 Subject: [PATCH 12/34] Sort_ecdsa_and_mod_builtins_private_inputs_by_idx (#1851) * Sort_ecdsa_and_mod_builtins_private_inputs_by_idx * Add signature `get_air_private_input` test and msg if somehow reaching unreachable clause * sort sigs before iterating --------- Co-authored-by: Pedro Fontana --- CHANGELOG.md | 3 + vm/src/vm/runners/builtin_runner/modulo.rs | 2 + vm/src/vm/runners/builtin_runner/signature.rs | 75 ++++++++++++++++++- 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4f8d6d455..2670010421 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,9 @@ * chore: update Rust required version to 1.81.0 [#1857](https://github.com/lambdaclass/cairo-vm/pull/1857) +* fix: [#1851](https://github.com/lambdaclass/cairo-vm/pull/1851): + * Fix unsorted signature and mod builtin outputs in air_private_input. + * feat(BREAKING): [#1824](https://github.com/lambdaclass/cairo-vm/pull/1824)[#1838](https://github.com/lambdaclass/cairo-vm/pull/1838): * Add support for dynamic layout * CLI change(BREAKING): The flag `cairo_layout_params_file` must be specified when using dynamic layout. diff --git a/vm/src/vm/runners/builtin_runner/modulo.rs b/vm/src/vm/runners/builtin_runner/modulo.rs index 3339c0b562..085e3549b6 100644 --- a/vm/src/vm/runners/builtin_runner/modulo.rs +++ b/vm/src/vm/runners/builtin_runner/modulo.rs @@ -263,6 +263,8 @@ impl ModBuiltinRunner { }); } + instances.sort_by_key(|input| input.index); + vec![PrivateInput::Mod(ModInput { instances, zero_value_address: relocation_table diff --git a/vm/src/vm/runners/builtin_runner/signature.rs b/vm/src/vm/runners/builtin_runner/signature.rs index 6e94206ef3..2b48bd8460 100644 --- a/vm/src/vm/runners/builtin_runner/signature.rs +++ b/vm/src/vm/runners/builtin_runner/signature.rs @@ -210,7 +210,17 @@ impl SignatureBuiltinRunner { pub fn air_private_input(&self, memory: &Memory) -> Vec { let mut private_inputs = vec![]; - for (addr, signature) in self.signatures.borrow().iter() { + + // Collect and sort the signatures by their index before the loop + let binding = self.signatures.borrow(); + let mut sorted_signatures: Vec<_> = binding.iter().collect(); + sorted_signatures.sort_by_key(|(addr, _)| { + addr.offset + .checked_div(CELLS_PER_SIGNATURE as usize) + .unwrap_or_default() + }); + + for (addr, signature) in sorted_signatures { if let (Ok(pubkey), Some(msg)) = ( memory.get_integer(*addr), (*addr + 1_usize) @@ -554,4 +564,67 @@ mod tests { assert_eq!(signature_a.s, signature_b.s); } } + #[test] + fn get_air_private_input() { + let mut builtin = SignatureBuiltinRunner::new(Some(512), true); + + builtin.base = 0; + + let signature1_r = Felt252::from(1234); + let signature1_s = Felt252::from(5678); + let signature2_r = Felt252::from(8765); + let signature2_s = Felt252::from(4321); + + let sig1_addr = Relocatable::from((builtin.base as isize, 0)); + let sig2_addr = Relocatable::from((builtin.base as isize, CELLS_PER_SIGNATURE as usize)); + + builtin + .add_signature(sig1_addr, &(signature1_r, signature1_s)) + .unwrap(); + builtin + .add_signature(sig2_addr, &(signature2_r, signature2_s)) + .unwrap(); + + let pubkey1 = Felt252::from(1111); + let msg1 = Felt252::from(2222); + let pubkey2 = Felt252::from(3333); + let msg2 = Felt252::from(4444); + + let segments = segments![ + ((0, 0), 1111), + ((0, 1), 2222), + ((0, 2), 3333), + ((0, 3), 4444) + ]; + let w1 = + Felt252::from(&div_mod(&BigInt::one(), &signature1_s.to_bigint(), &EC_ORDER).unwrap()); + + let w2 = + Felt252::from(&div_mod(&BigInt::one(), &signature2_s.to_bigint(), &EC_ORDER).unwrap()); + + let expected_private_inputs = vec![ + PrivateInput::Signature(PrivateInputSignature { + index: 0, + pubkey: pubkey1, + msg: msg1, + signature_input: SignatureInput { + r: signature1_r, + w: w1, + }, + }), + PrivateInput::Signature(PrivateInputSignature { + index: 1, + pubkey: pubkey2, + msg: msg2, + signature_input: SignatureInput { + r: signature2_r, + w: w2, + }, + }), + ]; + + let private_inputs = builtin.air_private_input(&segments.memory); + + assert_eq!(private_inputs, expected_private_inputs); + } } From 0d869361d5c2c6098170b751c1bdcb8eb071da8e Mon Sep 17 00:00:00 2001 From: Edgar Date: Thu, 14 Nov 2024 20:34:49 +0100 Subject: [PATCH 13/34] Fix broken num-prime crate (#1873) * Fix broken num-prime crate * changelog * try --- CHANGELOG.md | 2 ++ vm/src/math_utils/is_prime.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2670010421..b98d86551a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## Cairo-VM Changelog #### Upcoming Changes +* fix: [#1873](https://github.com/lambdaclass/cairo-vm/pull/1873) + * Fix broken num-prime `is_prime` call * fix: [#1868](https://github.com/lambdaclass/cairo-vm/pull/1855): * Adds logic to include the 3 new builtins in `builtin_segments` when serializing the output cairo pie's metadata. diff --git a/vm/src/math_utils/is_prime.rs b/vm/src/math_utils/is_prime.rs index 0e02ef1705..a39a9978a1 100644 --- a/vm/src/math_utils/is_prime.rs +++ b/vm/src/math_utils/is_prime.rs @@ -9,7 +9,7 @@ mod with_std { use num_bigint::BigUint; pub fn is_prime(n: &BigUint) -> bool { - num_prime::nt_funcs::is_prime(n, None).probably() + num_prime::nt_funcs::is_prime::(n, None).probably() } } From be5cb9a20b661cadc1382a987032141c6b80251a Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Tue, 19 Nov 2024 15:32:53 -0300 Subject: [PATCH 14/34] Fix scientific notation test (#1878) * fix test * fix test * reviews --- vm/src/serde/deserialize_program.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vm/src/serde/deserialize_program.rs b/vm/src/serde/deserialize_program.rs index 052d9ae09c..82771f7552 100644 --- a/vm/src/serde/deserialize_program.rs +++ b/vm/src/serde/deserialize_program.rs @@ -1492,8 +1492,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_felt_from_number_with_scientific_notation() { - let n = Number::deserialize(serde_json::Value::from(1000000000000000000000000000_u128)) - .unwrap(); + let n = Number::deserialize(serde_json::Value::from(1e27)).unwrap(); assert_eq!(n.to_string(), "1e27".to_owned()); assert_matches!( From 1e2d0421bb577cf994cb01a91d0631304138d159 Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Tue, 19 Nov 2024 16:27:37 -0300 Subject: [PATCH 15/34] Implement TestLessThanOrEqualAddress y EvalCircuit Hints (#1843) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add TestLessThanOrEqual match case + start implementing EvalCircuit Hint * add eval circuit functionallity * Add support for circuit builtins in cairo-run * possible fix to segment error in EvalCircuit Hint * remove unwanted files * format * fix NoStopPointer issue * tests passing * tests passing * default mod_builtins feature * format + update changelog * ignore circuit case if mod_builtin feature is not active * add mod_builtin feature to make run * format * fix tests * rewrite a little * format * stylling * stylling * reference * cargo lock * remove unwanted files * change test * format * better error handling * better error handling * better error handling * fix * fix CHANGELOG * fix unwraps * fix unwraps * fix unwraps * clippy --------- Co-authored-by: Julián González Calderón Co-authored-by: Pedro Fontana --- CHANGELOG.md | 2 + Cargo.lock | 582 +++++++++--------- cairo1-run/Cargo.toml | 1 + cairo1-run/Makefile | 4 +- cairo1-run/src/cairo_run.rs | 21 +- cairo1-run/src/main.rs | 12 +- cairo_programs/cairo-1-programs/circuit.cairo | 30 + .../serialized_output/circuit.cairo | 40 ++ .../cairo_1_hint_processor/circuit.rs | 311 ++++++++++ .../cairo_1_hint_processor/hint_processor.rs | 57 +- .../cairo_1_hint_processor/mod.rs | 1 + vm/src/vm/errors/hint_errors.rs | 4 + 12 files changed, 767 insertions(+), 298 deletions(-) create mode 100644 cairo_programs/cairo-1-programs/circuit.cairo create mode 100644 cairo_programs/cairo-1-programs/serialized_output/circuit.cairo create mode 100644 vm/src/hint_processor/cairo_1_hint_processor/circuit.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index b98d86551a..6516229b6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## Cairo-VM Changelog #### Upcoming Changes +* feat: add `EvalCircuit` and `TestLessThanOrEqualAddress` hints [#1843](https://github.com/lambdaclass/cairo-vm/pull/1843) + * fix: [#1873](https://github.com/lambdaclass/cairo-vm/pull/1873) * Fix broken num-prime `is_prime` call * fix: [#1868](https://github.com/lambdaclass/cairo-vm/pull/1855): diff --git a/Cargo.lock b/Cargo.lock index 4aef2cd4c3..20b66dc5cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,19 +4,13 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -61,9 +55,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "anes" @@ -73,9 +67,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -88,49 +82,49 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" dependencies = [ "derive_arbitrary", ] @@ -149,7 +143,7 @@ dependencies = [ "digest", "itertools 0.10.5", "num-bigint", - "num-traits 0.2.19", + "num-traits", "paste", "rustc_version", "zeroize", @@ -172,7 +166,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint", - "num-traits 0.2.19", + "num-traits", "proc-macro2", "quote", "syn 1.0.109", @@ -195,7 +189,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ - "num-traits 0.2.19", + "num-traits", "rand", ] @@ -222,9 +216,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-compression" -version = "0.4.12" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" +checksum = "0cb8f1d480b0ea3783ab015936d2a55c87e219676f0c0b7dec61494043f21857" dependencies = [ "brotli", "flate2", @@ -238,20 +232,20 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" @@ -304,17 +298,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.4", + "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -382,9 +376,9 @@ dependencies = [ [[package]] name = "brotli" -version = "6.0.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -403,9 +397,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", "serde", @@ -431,9 +425,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cairo-lang-casm" @@ -444,7 +438,7 @@ dependencies = [ "cairo-lang-utils", "indoc", "num-bigint", - "num-traits 0.2.19", + "num-traits", "parity-scale-codec", "serde", ] @@ -579,7 +573,7 @@ dependencies = [ "log", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "smol_str", ] @@ -598,7 +592,7 @@ dependencies = [ "colored", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "smol_str", "unescaper", @@ -631,7 +625,7 @@ checksum = "ac857ec4b564712f3e16e3314e23cc0787ab1c05cdfee83f1c8f9989a6eee40f" dependencies = [ "cairo-lang-debug", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -668,7 +662,7 @@ dependencies = [ "indoc", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "smol_str", "toml", @@ -690,7 +684,7 @@ dependencies = [ "lalrpop-util", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "regex", "rust-analyzer-salsa", "serde", @@ -713,7 +707,7 @@ dependencies = [ "cairo-lang-utils", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "thiserror", ] @@ -729,7 +723,7 @@ dependencies = [ "cairo-lang-utils", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "thiserror", ] @@ -750,7 +744,7 @@ dependencies = [ "cairo-lang-syntax", "cairo-lang-utils", "itertools 0.12.1", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "serde", "serde_json", @@ -773,7 +767,7 @@ dependencies = [ "indoc", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "starknet-types-core", "thiserror", ] @@ -832,7 +826,7 @@ dependencies = [ "itertools 0.12.1", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "serde", "serde_json", "sha3", @@ -851,7 +845,7 @@ dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", "num-bigint", - "num-traits 0.2.19", + "num-traits", "rust-analyzer-salsa", "smol_str", "unescaper", @@ -887,10 +881,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35df943ebcf8e1db11ee9f4f46f843dde5b71639ca79ea0d8caa7973f91d8b12" dependencies = [ "hashbrown 0.14.5", - "indexmap 2.5.0", + "indexmap 2.6.0", "itertools 0.12.1", "num-bigint", - "num-traits 0.2.19", + "num-traits", "schemars", "serde", ] @@ -922,7 +916,7 @@ dependencies = [ "num-bigint", "num-integer", "num-prime", - "num-traits 0.2.19", + "num-traits", "proptest", "rand", "rstest", @@ -963,7 +957,7 @@ dependencies = [ "include_dir", "mime_guess", "num-bigint", - "num-traits 0.2.19", + "num-traits", "serde", "thiserror-no-std", "tokio", @@ -993,7 +987,7 @@ dependencies = [ "itertools 0.11.0", "mimalloc", "num-bigint", - "num-traits 0.2.19", + "num-traits", "rstest", "serde_json", "thiserror", @@ -1007,9 +1001,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.15" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -1051,9 +1045,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -1061,9 +1055,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -1073,27 +1067,27 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" @@ -1123,18 +1117,18 @@ checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" [[package]] name = "const_format" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" dependencies = [ "proc-macro2", "quote", @@ -1152,9 +1146,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -1181,7 +1175,7 @@ dependencies = [ "criterion-plot", "is-terminal", "itertools 0.10.5", - "num-traits 0.2.19", + "num-traits", "once_cell", "oorandom", "plotters", @@ -1269,13 +1263,13 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -1364,9 +1358,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fixedbitset" @@ -1376,12 +1370,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -1390,6 +1384,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1407,9 +1407,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1422,9 +1422,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1432,15 +1432,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1449,32 +1449,32 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" @@ -1484,9 +1484,9 @@ checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1502,9 +1502,9 @@ dependencies = [ [[package]] name = "genco" -version = "0.17.9" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afac3cbb14db69ac9fef9cdb60d8a87e39a7a527f85a81a923436efa40ad42c6" +checksum = "a35958104272e516c2a5f66a9d82fba4784d2b585fc1e2358b8f96e15d342995" dependencies = [ "genco-macros", "relative-path", @@ -1513,13 +1513,13 @@ dependencies = [ [[package]] name = "genco-macros" -version = "0.17.9" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "553630feadf7b76442b0849fd25fdf89b860d933623aec9693fed19af0400c78" +checksum = "43eaff6bbc0b3a878361aced5ec6a2818ee7c541c5b33b5880dfa9a86c23e9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -1547,15 +1547,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "globset" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr", @@ -1566,12 +1566,12 @@ dependencies = [ [[package]] name = "good_lp" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3198bd13dea84c76a64621d6ee8ee26a4960a9a0d538eca95ca8f1320a469ac9" +checksum = "97630e1e456d7081c524488a87d8f8f7ed0fd3100ba10c55e3cfa7add5ce05c6" dependencies = [ "fnv", - "minilp", + "microlp", ] [[package]] @@ -1601,6 +1601,17 @@ dependencies = [ "serde", ] +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "heck" version = "0.4.1" @@ -1679,9 +1690,9 @@ checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1691,9 +1702,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -1735,9 +1746,9 @@ checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" [[package]] name = "ignore" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" dependencies = [ "crossbeam-deque", "globset", @@ -1798,12 +1809,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.1", "serde", ] @@ -1815,9 +1826,9 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "iri-string" -version = "0.7.2" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f5f6c2df22c009ac44f6f1499308e7a3ac7ba42cd2378475cc691510e1eef1b" +checksum = "dc0f0a572e8ffe56e2ff4f769f32ffe919282c3916799f8b68688b6030063bea" dependencies = [ "memchr", "serde", @@ -1933,9 +1944,9 @@ dependencies = [ [[package]] name = "lambdaworks-crypto" -version = "0.7.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb5d4f22241504f7c7b8d2c3a7d7835d7c07117f10bff2a7d96a9ef6ef217c3" +checksum = "bbc2a4da0d9e52ccfe6306801a112e81a8fc0c76aa3e4449fefeda7fef72bb34" dependencies = [ "lambdaworks-math", "serde", @@ -1945,9 +1956,9 @@ dependencies = [ [[package]] name = "lambdaworks-math" -version = "0.7.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "358e172628e713b80a530a59654154bfc45783a6ed70ea284839800cebdf8f97" +checksum = "d1bd2632acbd9957afc5aeec07ad39f078ae38656654043bf16e046fa2730e23" dependencies = [ "serde", "serde_json", @@ -1964,15 +1975,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.158" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libmimalloc-sys" @@ -2018,11 +2029,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.15.1", ] [[package]] @@ -2033,10 +2044,11 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "matrixmultiply" -version = "0.2.4" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916806ba0031cd542105d916a97c8572e1fa6dd79c9c51e7eb43a09ec2dd84c1" +checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" dependencies = [ + "autocfg", "rawpointer", ] @@ -2046,6 +2058,16 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "microlp" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4190b5ca62abfbc95a81d57f4a8e3e3872289d656f3eeea5820b3046a1f81d4b" +dependencies = [ + "log", + "sprs", +] + [[package]] name = "mimalloc" version = "0.1.43" @@ -2071,31 +2093,12 @@ dependencies = [ "unicase", ] -[[package]] -name = "minilp" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a7750a9e5076c660b7bec5e6457b4dbff402b9863c8d112891434e18fd5385" -dependencies = [ - "log", - "sprs", -] - [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -2119,14 +2122,16 @@ dependencies = [ [[package]] name = "ndarray" -version = "0.13.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac06db03ec2f46ee0ecdca1a1c34a99c0d188a0d83439b84bf0cb4b386e4ab09" +checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" dependencies = [ "matrixmultiply", "num-complex", "num-integer", - "num-traits 0.2.19", + "num-traits", + "portable-atomic", + "portable-atomic-util", "rawpointer", ] @@ -2163,19 +2168,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", - "num-traits 0.2.19", + "num-traits", "rand", "serde", ] [[package]] name = "num-complex" -version = "0.2.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ - "autocfg", - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -2184,7 +2188,7 @@ version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -2195,7 +2199,7 @@ checksum = "64a5fe11d4135c3bcdf3a95b18b194afa9608a5f6ff034f5d857bc9a27fb0119" dependencies = [ "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -2210,19 +2214,10 @@ dependencies = [ "num-bigint", "num-integer", "num-modular", - "num-traits 0.2.19", + "num-traits", "rand", ] -[[package]] -name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -dependencies = [ - "num-traits 0.2.19", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -2235,18 +2230,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" @@ -2334,7 +2329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.5.0", + "indexmap 2.6.0", ] [[package]] @@ -2354,29 +2349,29 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2386,17 +2381,17 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plotters" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ - "num-traits 0.2.19", + "num-traits", "plotters-backend", "plotters-svg", "wasm-bindgen", @@ -2405,19 +2400,34 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + +[[package]] +name = "portable-atomic-util" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90a7d5beecc52a491b54d6dd05c7a45ba1801666a5baad9fdbfc6fef8d2d206c" +dependencies = [ + "portable-atomic", +] + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -2435,9 +2445,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -2454,9 +2464,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -2471,7 +2481,7 @@ dependencies = [ "bit-vec", "bitflags 2.6.0", "lazy_static", - "num-traits 0.2.19", + "num-traits", "rand", "rand_chacha", "rand_xorshift", @@ -2569,9 +2579,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -2589,9 +2599,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -2601,9 +2611,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -2612,9 +2622,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "relative-path" @@ -2664,7 +2674,7 @@ version = "0.17.0-pre.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719825638c59fd26a55412a24561c7c5bcf54364c88b9a7a04ba08a6eafaba8d" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "lock_api", "oorandom", "parking_lot", @@ -2684,7 +2694,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -2694,7 +2704,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ "arrayvec", - "num-traits 0.2.19", + "num-traits", ] [[package]] @@ -2720,9 +2730,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" dependencies = [ "bitflags 2.6.0", "errno", @@ -2733,9 +2743,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "rusty-fork" @@ -2786,7 +2796,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -2812,22 +2822,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -2838,14 +2848,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -2865,9 +2875,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -2968,13 +2978,14 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "sprs" -version = "0.7.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec63571489873d4506683915840eeb1bb16b3198ee4894cc6f2fe3013d505e56" +checksum = "704ef26d974e8a452313ed629828cd9d4e4fa34667ca1ad9d6b1fffa43c6e166" dependencies = [ "ndarray", "num-complex", - "num-traits 0.1.43", + "num-traits", + "smallvec", ] [[package]] @@ -2994,7 +3005,7 @@ dependencies = [ "hmac", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "rfc6979", "sha2", "starknet-crypto-codegen", @@ -3011,7 +3022,7 @@ checksum = "bbc159a1934c7be9761c237333a57febe060ace2bc9e3b337a59a37af206d19f" dependencies = [ "starknet-curve", "starknet-ff", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -3037,9 +3048,9 @@ dependencies = [ [[package]] name = "starknet-types-core" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6bacf0ba19bc721e518bc4bf389ff13daa8a7c5db5fd320600473b8aa9fcbd" +checksum = "fa1b9e01ccb217ab6d475c5cda05dbb22c30029f7bb52b192a010a00d77a3d74" dependencies = [ "arbitrary", "lambdaworks-crypto", @@ -3047,7 +3058,7 @@ dependencies = [ "lazy_static", "num-bigint", "num-integer", - "num-traits 0.2.19", + "num-traits", "serde", ] @@ -3089,9 +3100,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -3112,9 +3123,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -3136,22 +3147,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -3205,9 +3216,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -3227,14 +3238,14 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -3266,11 +3277,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -3355,7 +3366,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -3395,9 +3406,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" dependencies = [ "serde", "stable_deref_trait", @@ -3432,30 +3443,27 @@ dependencies = [ [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "utf8parse" @@ -3465,9 +3473,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", ] @@ -3539,7 +3547,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -3573,7 +3581,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3606,7 +3614,7 @@ checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -3811,9 +3819,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -3844,9 +3852,9 @@ checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852" [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" @@ -3866,7 +3874,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -3886,7 +3894,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] diff --git a/cairo1-run/Cargo.toml b/cairo1-run/Cargo.toml index 45944c55da..7dc229228b 100644 --- a/cairo1-run/Cargo.toml +++ b/cairo1-run/Cargo.toml @@ -34,3 +34,4 @@ num-bigint.workspace = true [features] default = ["with_mimalloc"] with_mimalloc = ["dep:mimalloc"] +mod_builtin = ["cairo-vm/mod_builtin"] diff --git a/cairo1-run/Makefile b/cairo1-run/Makefile index 238b2fea72..97ff8dec6e 100644 --- a/cairo1-run/Makefile +++ b/cairo1-run/Makefile @@ -3,10 +3,10 @@ CAIRO_1_FOLDER=../cairo_programs/cairo-1-programs $(CAIRO_1_FOLDER)/%.trace: $(CAIRO_1_FOLDER)/%.cairo - cargo run --release $< --trace_file $@ --layout all_cairo + cargo run --release -F mod_builtin $< --trace_file $@ --layout all_cairo $(CAIRO_1_FOLDER)/%.memory: $(CAIRO_1_FOLDER)/%.cairo - cargo run --release $< --memory_file $@ --layout all_cairo + cargo run --release -F mod_builtin $< --memory_file $@ --layout all_cairo CAIRO_1_PROGRAMS=$(wildcard ../cairo_programs/cairo-1-programs/*.cairo) TRACES:=$(patsubst $(CAIRO_1_FOLDER)/%.cairo, $(CAIRO_1_FOLDER)/%.trace, $(CAIRO_1_PROGRAMS)) diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index 8a293c680e..b196bda230 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -11,12 +11,13 @@ use cairo_lang_casm::{ use cairo_lang_sierra::{ extensions::{ bitwise::BitwiseType, + circuit::{AddModType, MulModType}, core::{CoreLibfunc, CoreType}, ec::EcOpType, gas::GasBuiltinType, pedersen::PedersenType, poseidon::PoseidonType, - range_check::RangeCheckType, + range_check::{RangeCheck96Type, RangeCheckType}, segment_arena::SegmentArenaType, starknet::syscalls::SystemType, ConcreteType, NamedType, @@ -670,6 +671,9 @@ fn create_entry_code( BuiltinName::ec_op => builtin_vars[&EcOpType::ID], BuiltinName::poseidon => builtin_vars[&PoseidonType::ID], BuiltinName::segment_arena => builtin_vars[&SegmentArenaType::ID], + BuiltinName::add_mod => builtin_vars[&AddModType::ID], + BuiltinName::mul_mod => builtin_vars[&MulModType::ID], + BuiltinName::range_check96 => builtin_vars[&RangeCheck96Type::ID], _ => unreachable!(), }; if copy_to_output_builtin { @@ -902,6 +906,13 @@ fn get_function_builtins( let mut builtin_offset: HashMap = HashMap::new(); let mut current_offset = 3; for (debug_name, builtin_name, sierra_id) in [ + ("MulMod", BuiltinName::mul_mod, MulModType::ID), + ("AddMod", BuiltinName::add_mod, AddModType::ID), + ( + "RangeCheck96", + BuiltinName::range_check96, + RangeCheck96Type::ID, + ), ("Poseidon", BuiltinName::poseidon, PoseidonType::ID), ("EcOp", BuiltinName::ec_op, EcOpType::ID), ("Bitwise", BuiltinName::bitwise, BitwiseType::ID), @@ -962,8 +973,11 @@ fn is_implicit_generic_id(generic_ty: &GenericTypeId) -> bool { PedersenType::ID, PoseidonType::ID, RangeCheckType::ID, + RangeCheck96Type::ID, SegmentArenaType::ID, SystemType::ID, + MulModType::ID, + AddModType::ID, ] .contains(generic_ty) } @@ -1158,6 +1172,9 @@ fn finalize_builtins( "Pedersen" => BuiltinName::pedersen, "Output" => BuiltinName::output, "Ecdsa" => BuiltinName::ecdsa, + "AddMod" => BuiltinName::add_mod, + "MulMod" => BuiltinName::mul_mod, + "RangeCheck96" => BuiltinName::range_check96, _ => { stack_pointer.offset += size as usize; continue; @@ -1246,7 +1263,7 @@ fn serialize_output_inner<'a>( .expect("Missing return value") .get_relocatable() .expect("Box Pointer is not Relocatable"); - let type_size = type_sizes[&info.ty].try_into().expect("could not parse to usize"); + let type_size = type_sizes[&info.ty].try_into().expect("could not parse to usize"); let data = vm .get_continuous_range(ptr, type_size) .expect("Failed to extract value from nullable ptr"); diff --git a/cairo1-run/src/main.rs b/cairo1-run/src/main.rs index edad364df1..6ec7d6d32f 100644 --- a/cairo1-run/src/main.rs +++ b/cairo1-run/src/main.rs @@ -38,7 +38,7 @@ struct Args { air_public_input: Option, #[clap( long = "air_private_input", - requires_all = ["proof_mode", "trace_file", "memory_file"] + requires_all = ["proof_mode", "trace_file", "memory_file"] )] air_private_input: Option, #[clap( @@ -436,8 +436,14 @@ mod tests { Some("[17 18]"), Some("[17 18]") )] - - fn test_run_progarm( + #[cfg_attr(feature = "mod_builtin", case( + "circuit.cairo", + "36699840570117848377038274035 72042528776886984408017100026 54251667697617050795983757117 7", + "[36699840570117848377038274035 72042528776886984408017100026 54251667697617050795983757117 7]", + None, + None + ))] + fn test_run_program( #[case] program: &str, #[case] expected_output: &str, #[case] expected_serialized_output: &str, diff --git a/cairo_programs/cairo-1-programs/circuit.cairo b/cairo_programs/cairo-1-programs/circuit.cairo new file mode 100644 index 0000000000..5624c92ccc --- /dev/null +++ b/cairo_programs/cairo-1-programs/circuit.cairo @@ -0,0 +1,30 @@ +use core::circuit::{ + RangeCheck96, AddMod, MulMod, u96, CircuitElement, CircuitInput, circuit_add, + circuit_sub, circuit_mul, circuit_inverse, EvalCircuitTrait, u384, + CircuitOutputsTrait, CircuitModulus, AddInputResultTrait, CircuitInputs, +}; + +fn main() -> u384 { + let in1 = CircuitElement::> {}; + let in2 = CircuitElement::> {}; + let add1 = circuit_add(in1, in2); + let mul1 = circuit_mul(add1, in1); + let mul2 = circuit_mul(mul1, add1); + let inv1 = circuit_inverse(mul2); + let sub1 = circuit_sub(inv1, in2); + let sub2 = circuit_sub(sub1, mul2); + let inv2 = circuit_inverse(sub2); + let add2 = circuit_add(inv2, inv2); + + let modulus = TryInto::<_, CircuitModulus>::try_into([17, 14, 14, 14]).unwrap(); + + let outputs = (add2,) + .new_inputs() + .next([9, 2, 9, 3]) + .next([5, 7, 0, 8]) + .done() + .eval(modulus) + .unwrap(); + + outputs.get_output(add2) +} diff --git a/cairo_programs/cairo-1-programs/serialized_output/circuit.cairo b/cairo_programs/cairo-1-programs/serialized_output/circuit.cairo new file mode 100644 index 0000000000..85e9f7e9a6 --- /dev/null +++ b/cairo_programs/cairo-1-programs/serialized_output/circuit.cairo @@ -0,0 +1,40 @@ +use core::circuit::{ + RangeCheck96, AddMod, MulMod, u96, CircuitElement, CircuitInput, circuit_add, + circuit_sub, circuit_mul, circuit_inverse, EvalCircuitTrait, u384, + CircuitOutputsTrait, CircuitModulus, AddInputResultTrait, CircuitInputs, +}; +use array::ArrayTrait; + +fn main() -> Array { + let in1 = CircuitElement::> {}; + let in2 = CircuitElement::> {}; + let add1 = circuit_add(in1, in2); + let mul1 = circuit_mul(add1, in1); + let mul2 = circuit_mul(mul1, add1); + let inv1 = circuit_inverse(mul2); + let sub1 = circuit_sub(inv1, in2); + let sub2 = circuit_sub(sub1, mul2); + let inv2 = circuit_inverse(sub2); + let add2 = circuit_add(inv2, inv2); + + let modulus = TryInto::<_, CircuitModulus>::try_into([17, 14, 14, 14]).unwrap(); + + let outputs = (add2,) + .new_inputs() + .next([9, 2, 9, 3]) + .next([5, 7, 0, 8]) + .done() + .eval(modulus) + .unwrap(); + + let circuit_output = outputs.get_output(add2); + + let mut output: Array = ArrayTrait::new(); + + circuit_output.limb0.serialize(ref output); + circuit_output.limb1.serialize(ref output); + circuit_output.limb2.serialize(ref output); + circuit_output.limb3.serialize(ref output); + + output +} diff --git a/vm/src/hint_processor/cairo_1_hint_processor/circuit.rs b/vm/src/hint_processor/cairo_1_hint_processor/circuit.rs new file mode 100644 index 0000000000..1b23a7f0e3 --- /dev/null +++ b/vm/src/hint_processor/cairo_1_hint_processor/circuit.rs @@ -0,0 +1,311 @@ +// Most of the `EvalCircuit` implementation is derived from the `cairo-lang-runner` crate. +// https://github.com/starkware-libs/cairo/blob/main/crates/cairo-lang-runner/src/casm_run/circuit.rs + +use core::ops::Deref; + +use ark_ff::{One, Zero}; +use num_bigint::{BigInt, BigUint, ToBigInt}; +use num_integer::Integer; +use num_traits::Signed; +use starknet_types_core::felt::Felt; + +use crate::{ + stdlib::boxed::Box, + types::relocatable::{MaybeRelocatable, Relocatable}, + vm::{ + errors::{hint_errors::HintError, memory_errors::MemoryError}, + vm_core::VirtualMachine, + }, +}; + +// A gate is defined by 3 offsets, the first two are the inputs and the third is the output. +const OFFSETS_PER_GATE: usize = 3; +// Represents the number of limbs use to represent a single value in a circuit +const LIMBS_COUNT: usize = 4; +// Representes the size of a MulMod and AddMod instance +const MOD_BUILTIN_INSTACE_SIZE: usize = 7; + +struct Circuit<'a> { + vm: &'a mut VirtualMachine, + values_ptr: Relocatable, + add_mod_offsets: Relocatable, + mul_mod_offsets: Relocatable, + modulus: BigUint, +} + +impl Circuit<'_> { + fn read_add_mod_value(&mut self, offset: usize) -> Result, MemoryError> { + self.read_circuit_value((self.add_mod_offsets + offset)?) + } + + fn read_mul_mod_value(&mut self, offset: usize) -> Result, MemoryError> { + self.read_circuit_value((self.mul_mod_offsets + offset)?) + } + + fn read_circuit_value(&mut self, offset: Relocatable) -> Result, MemoryError> { + let value_ptr = self.get_value_ptr(offset)?; + read_circuit_value(self.vm, value_ptr) + } + + fn write_add_mod_value(&mut self, offset: usize, value: BigUint) -> Result<(), MemoryError> { + self.write_circuit_value((self.add_mod_offsets + offset)?, value)?; + + Ok(()) + } + + fn write_mul_mod_value(&mut self, offset: usize, value: BigUint) -> Result<(), MemoryError> { + self.write_circuit_value((self.mul_mod_offsets + offset)?, value)?; + + Ok(()) + } + + fn write_circuit_value( + &mut self, + offset: Relocatable, + value: BigUint, + ) -> Result<(), MemoryError> { + let value_ptr = self.get_value_ptr(offset)?; + write_circuit_value(self.vm, value_ptr, value)?; + + Ok(()) + } + + fn get_value_ptr(&self, address: Relocatable) -> Result { + (self.values_ptr + self.vm.get_integer(address)?.as_ref()).map_err(MemoryError::Math) + } +} + +fn read_circuit_value( + vm: &mut VirtualMachine, + add: Relocatable, +) -> Result, MemoryError> { + let mut res = BigUint::zero(); + + for l in (0..LIMBS_COUNT).rev() { + let add_l = (add + l)?; + match vm.get_maybe(&add_l) { + Some(MaybeRelocatable::Int(limb)) => res = (res << 96) + limb.to_biguint(), + _ => return Ok(None), + } + } + + Ok(Some(res)) +} + +fn write_circuit_value( + vm: &mut VirtualMachine, + add: Relocatable, + mut value: BigUint, +) -> Result<(), MemoryError> { + for l in 0..LIMBS_COUNT { + // get the nth limb from a circuit value + let (new_value, rem) = value.div_rem(&(BigUint::one() << 96u8)); + vm.insert_value((add + l)?, Felt::from(rem))?; + value = new_value; + } + + Ok(()) +} + +// Finds the inverse of a value. +// +// If the value has no inverse, find a nullifier so that: +// value * nullifier = 0 (mod modulus) +fn find_inverse(value: BigUint, modulus: &BigUint) -> Result<(bool, BigUint), HintError> { + let ex_gcd = value + .to_bigint() + .ok_or(HintError::BigUintToBigIntFail)? + .extended_gcd(&modulus.to_bigint().ok_or(HintError::BigUintToBigIntFail)?); + + let gcd = ex_gcd + .gcd + .to_biguint() + .ok_or(HintError::BigIntToBigUintFail)?; + if gcd.is_one() { + return Ok((true, get_modulus(&ex_gcd.x, modulus))); + } + + let nullifier = modulus / gcd; + + Ok((false, nullifier)) +} + +fn get_modulus(value: &BigInt, modulus: &BigUint) -> BigUint { + let value_magnitud = value.magnitude().mod_floor(modulus); + if value.is_negative() { + modulus - value_magnitud + } else { + value_magnitud + } +} + +fn compute_gates( + vm: &mut VirtualMachine, + values_ptr: Relocatable, + add_mod_offsets: Relocatable, + n_add_mods: usize, + mul_mod_offsets: Relocatable, + n_mul_mods: usize, + modulus_ptr: Relocatable, +) -> Result { + let modulus = read_circuit_value(vm, modulus_ptr)?.ok_or(HintError::Memory( + MemoryError::ExpectedInteger(Box::from(modulus_ptr)), + ))?; + + let mut circuit = Circuit { + vm, + values_ptr, + add_mod_offsets, + mul_mod_offsets, + modulus, + }; + + let mut addmod_idx = 0; + let mut mulmod_idx = 0; + + // Only mul gates can make the evaluation fail + let mut first_failure_idx = n_mul_mods; + + loop { + while addmod_idx < n_add_mods { + let lhs = circuit.read_add_mod_value(3 * addmod_idx)?; + let rhs = circuit.read_add_mod_value(3 * addmod_idx + 1)?; + + match (lhs, rhs) { + (Some(l), Some(r)) => { + let res = (l + r) % &circuit.modulus; + circuit.write_add_mod_value(3 * addmod_idx + 2, res)?; + } + // sub gate: lhs = res - rhs + (None, Some(r)) => { + let Some(res) = circuit.read_add_mod_value(3 * addmod_idx + 2)? else { + break; + }; + let value = (res + &circuit.modulus - r) % &circuit.modulus; + circuit.write_add_mod_value(3 * addmod_idx, value)?; + } + _ => break, + } + + addmod_idx += 1; + } + + if mulmod_idx == n_mul_mods { + break; + } + + let lhs = circuit.read_mul_mod_value(3 * mulmod_idx)?; + let rhs = circuit.read_mul_mod_value(3 * mulmod_idx + 1)?; + + match (lhs, rhs) { + (Some(l), Some(r)) => { + let res = (l * r) % &circuit.modulus; + circuit.write_mul_mod_value(3 * mulmod_idx + 2, res)?; + } + // inverse gate: lhs = 1 / rhs + (None, Some(r)) => { + let (success, res) = find_inverse(r, &circuit.modulus)?; + circuit.write_mul_mod_value(3 * mulmod_idx, res)?; + + if !success { + first_failure_idx = mulmod_idx; + break; + } + } + _ => { + // this should be unreachable as it would mean that the + //circuit being evaluated is not complete and therefore invalid + return Err(HintError::CircuitEvaluationFailed(Box::from( + "Unexpected None value while filling mul_mod gate", + ))); + } + } + + mulmod_idx += 1; + } + + Ok(first_failure_idx) +} + +fn fill_instances( + vm: &mut VirtualMachine, + built_ptr: Relocatable, + n_instances: usize, + modulus: [Felt; LIMBS_COUNT], + values_ptr: Relocatable, + mut offsets_ptr: Relocatable, +) -> Result<(), HintError> { + for i in 0..n_instances { + let instance_ptr = (built_ptr + i * MOD_BUILTIN_INSTACE_SIZE)?; + + for (idx, value) in modulus.iter().enumerate() { + vm.insert_value((instance_ptr + idx)?, *value)?; + } + + vm.insert_value((instance_ptr + 4)?, values_ptr)?; + vm.insert_value((instance_ptr + 5)?, offsets_ptr)?; + offsets_ptr += OFFSETS_PER_GATE; + vm.insert_value((instance_ptr + 6)?, n_instances - i)?; + } + Ok(()) +} + +/// Computes the circuit. +/// +/// If theres a failure, it returs the index of the gate in which the failure occurred, else +/// returns the total amount of mul gates. +pub fn eval_circuit( + vm: &mut VirtualMachine, + n_add_mods: usize, + add_mod_builtin_address: Relocatable, + n_mul_mods: usize, + mul_mod_builtin_address: Relocatable, +) -> Result<(), HintError> { + let modulus_ptr = mul_mod_builtin_address; + let mul_mod_values_offset = 4; + let mul_mod_offset = 5; + + let values_ptr = vm.get_relocatable((mul_mod_builtin_address + mul_mod_values_offset)?)?; + let mul_mod_offsets = vm.get_relocatable((mul_mod_builtin_address + mul_mod_offset)?)?; + let add_mod_offsets = if n_add_mods == 0 { + mul_mod_offsets + } else { + vm.get_relocatable((add_mod_builtin_address + mul_mod_offset)?)? + }; + + let n_computed_gates = compute_gates( + vm, + values_ptr, + add_mod_offsets, + n_add_mods, + mul_mod_offsets, + n_mul_mods, + modulus_ptr, + )?; + + let modulus: [Felt; 4] = [ + *vm.get_integer(modulus_ptr)?.deref(), + *vm.get_integer((modulus_ptr + 1)?)?.deref(), + *vm.get_integer((modulus_ptr + 2)?)?.deref(), + *vm.get_integer((modulus_ptr + 3)?)?.deref(), + ]; + + fill_instances( + vm, + add_mod_builtin_address, + n_add_mods, + modulus, + values_ptr, + add_mod_offsets, + )?; + fill_instances( + vm, + mul_mod_builtin_address, + n_computed_gates, + modulus, + values_ptr, + mul_mod_offsets, + )?; + + Ok(()) +} diff --git a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs index 0caf9c4e9c..9b6e4b8651 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs @@ -1,3 +1,4 @@ +use super::circuit; use super::dict_manager::DictManagerExecScope; use super::hint_processor_utils::*; use crate::any_box; @@ -10,7 +11,7 @@ use crate::vm::runners::cairo_runner::RunResources; use crate::Felt252; use crate::{ hint_processor::hint_processor_definition::HintProcessorLogic, - types::exec_scope::ExecutionScopes, + types::{errors::math_errors::MathError, exec_scope::ExecutionScopes}, vm::errors::vm_errors::VirtualMachineError, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; @@ -87,9 +88,12 @@ impl Cairo1HintProcessor { Hint::Core(CoreHintBase::Core(CoreHint::TestLessThan { lhs, rhs, dst })) => { self.test_less_than(vm, lhs, rhs, dst) } - Hint::Core(CoreHintBase::Core(CoreHint::TestLessThanOrEqual { lhs, rhs, dst })) => { - self.test_less_than_or_equal(vm, lhs, rhs, dst) - } + Hint::Core(CoreHintBase::Core(CoreHint::TestLessThanOrEqual { lhs, rhs, dst })) + | Hint::Core(CoreHintBase::Core(CoreHint::TestLessThanOrEqualAddress { + lhs, + rhs, + dst, + })) => self.test_less_than_or_equal(vm, lhs, rhs, dst), Hint::Core(CoreHintBase::Deprecated(DeprecatedHint::Felt252DictRead { dict_ptr, key, @@ -276,6 +280,12 @@ impl Cairo1HintProcessor { t_or_k0, t_or_k1, ), + Hint::Core(CoreHintBase::Core(CoreHint::EvalCircuit { + n_add_mods, + add_mod_builtin, + n_mul_mods, + mul_mod_builtin, + })) => self.eval_circuit(vm, n_add_mods, add_mod_builtin, n_mul_mods, mul_mod_builtin), Hint::Starknet(StarknetHint::Cheatcode { selector, .. }) => { let selector = &selector.value.to_bytes_be().1; let selector = crate::stdlib::str::from_utf8(selector).map_err(|_| { @@ -1194,6 +1204,45 @@ impl Cairo1HintProcessor { } Ok(()) } + fn eval_circuit( + &self, + vm: &mut VirtualMachine, + n_add_mods: &ResOperand, + add_mod_builtin_ptr: &ResOperand, + n_mul_mods: &ResOperand, + mul_mod_builtin_ptr: &ResOperand, + ) -> Result<(), HintError> { + let n_add_mods = get_val(vm, n_add_mods)?; + let n_add_mods = + n_add_mods + .to_usize() + .ok_or(HintError::Math(MathError::Felt252ToUsizeConversion( + Box::from(n_add_mods), + )))?; + let n_mul_mods = get_val(vm, n_mul_mods)?; + let n_mul_mods = + n_mul_mods + .to_usize() + .ok_or(HintError::Math(MathError::Felt252ToUsizeConversion( + Box::from(n_mul_mods), + )))?; + + let (add_mod_builtin_base, add_mod_builtin_offset) = extract_buffer(add_mod_builtin_ptr)?; + let (mul_mod_builtin_base, mul_mod_builtin_offset) = extract_buffer(mul_mod_builtin_ptr)?; + + let add_mod_builtin_address = get_ptr(vm, add_mod_builtin_base, &add_mod_builtin_offset)?; + let mul_mod_builtin_address = get_ptr(vm, mul_mod_builtin_base, &mul_mod_builtin_offset)?; + + circuit::eval_circuit( + vm, + n_add_mods, + add_mod_builtin_address, + n_mul_mods, + mul_mod_builtin_address, + )?; + + Ok(()) + } } impl HintProcessorLogic for Cairo1HintProcessor { diff --git a/vm/src/hint_processor/cairo_1_hint_processor/mod.rs b/vm/src/hint_processor/cairo_1_hint_processor/mod.rs index 29d5f47bd3..d6d964081e 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/mod.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/mod.rs @@ -1,3 +1,4 @@ +pub mod circuit; pub mod dict_manager; pub mod hint_processor; pub mod hint_processor_utils; diff --git a/vm/src/vm/errors/hint_errors.rs b/vm/src/vm/errors/hint_errors.rs index 0594a2f518..849d38288d 100644 --- a/vm/src/vm/errors/hint_errors.rs +++ b/vm/src/vm/errors/hint_errors.rs @@ -154,6 +154,8 @@ pub enum HintError { BigintToU32Fail, #[error("BigInt to BigUint failed, BigInt is negative")] BigIntToBigUintFail, + #[error("BigUint to BigInt failed")] + BigUintToBigIntFail, #[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0} is out of range")] ValueOutOfRange(Box), #[error("Assertion failed, 0 <= ids.a % PRIME < range_check_builtin.bound \n a = {0} is out of range")] @@ -190,6 +192,8 @@ pub enum HintError { ExcessBalanceKeyError(Box), #[error("excess_balance_func: Failed to calculate {0}")] ExcessBalanceCalculationFailed(Box), + #[error("circuit evalution: {0}")] + CircuitEvaluationFailed(Box), } #[cfg(test)] From 388a4e51001377717b7e4c902c35f8e271c92ad7 Mon Sep 17 00:00:00 2001 From: Edgar Date: Thu, 21 Nov 2024 12:21:50 +0100 Subject: [PATCH 16/34] v2.0.0-rc1 (#1876) Co-authored-by: Franco Giachetta --- CHANGELOG.md | 3 +++ Cargo.lock | 53 ++++++++++++++++++++++++++-------------------------- Cargo.toml | 6 +++--- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6516229b6f..2e843ee992 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ## Cairo-VM Changelog #### Upcoming Changes + +#### [2.0.0-rc1] - 2024-11-20 + * feat: add `EvalCircuit` and `TestLessThanOrEqualAddress` hints [#1843](https://github.com/lambdaclass/cairo-vm/pull/1843) * fix: [#1873](https://github.com/lambdaclass/cairo-vm/pull/1873) diff --git a/Cargo.lock b/Cargo.lock index 20b66dc5cd..5d13555d68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -891,7 +891,7 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "2.0.0-rc0" +version = "2.0.0-rc1" dependencies = [ "anyhow", "arbitrary", @@ -935,7 +935,7 @@ dependencies = [ [[package]] name = "cairo-vm-cli" -version = "2.0.0-rc0" +version = "2.0.0-rc1" dependencies = [ "assert_matches", "bincode", @@ -950,7 +950,7 @@ dependencies = [ [[package]] name = "cairo-vm-tracer" -version = "2.0.0-rc0" +version = "2.0.0-rc1" dependencies = [ "axum", "cairo-vm", @@ -969,7 +969,7 @@ dependencies = [ [[package]] name = "cairo1-run" -version = "2.0.0-rc0" +version = "2.0.0-rc1" dependencies = [ "assert_matches", "bincode", @@ -1644,7 +1644,7 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hint_accountant" -version = "2.0.0-rc0" +version = "2.0.0-rc1" dependencies = [ "cairo-vm", "serde", @@ -1725,7 +1725,7 @@ dependencies = [ [[package]] name = "hyper_threading" -version = "2.0.0-rc0" +version = "2.0.0-rc1" dependencies = [ "cairo-vm", "rayon", @@ -1880,9 +1880,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "7a73e9fe3c49d7afb2ace819fa181a287ce54a0983eda4e0eb05c22f82ffe534" [[package]] name = "jobserver" @@ -1975,9 +1975,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.162" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libm" @@ -2257,28 +2257,29 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parity-scale-codec" -version = "3.6.12" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +checksum = "8be4817d39f3272f69c59fe05d0535ae6456c2dc2fa1ba02910296c7e0a5c590" dependencies = [ "arrayvec", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", + "rustversion", "serde", ] [[package]] name = "parity-scale-codec-derive" -version = "3.6.12" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +checksum = "8781a75c6205af67215f382092b6e0a4ff3734798523e69073d4bcd294ec767b" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] @@ -2730,9 +2731,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -2853,9 +2854,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -3449,9 +3450,9 @@ checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" @@ -3619,7 +3620,7 @@ dependencies = [ [[package]] name = "wasm-demo" -version = "2.0.0-rc0" +version = "2.0.0-rc1" dependencies = [ "cairo-vm", "console_error_panic_hook", @@ -3837,18 +3838,18 @@ dependencies = [ [[package]] name = "xshell" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db0ab86eae739efd1b054a8d3d16041914030ac4e01cd1dca0cf252fd8b6437" +checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d" dependencies = [ "xshell-macros", ] [[package]] name = "xshell-macros" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d422e8e38ec76e2f06ee439ccc765e9c6a9638b9e7c9f2e8255e4d41e8bd852" +checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547" [[package]] name = "yansi" diff --git a/Cargo.toml b/Cargo.toml index 7338b83ee0..cd18cb6a45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ exclude = ["ensure-no_std"] resolver = "2" [workspace.package] -version = "2.0.0-rc0" +version = "2.0.0-rc1" edition = "2021" license = "Apache-2.0" repository = "https://github.com/lambdaclass/cairo-vm/" @@ -24,8 +24,8 @@ readme = "README.md" keywords = ["starknet", "cairo", "vm", "wasm", "no_std"] [workspace.dependencies] -cairo-vm = { path = "./vm", version = "2.0.0-rc0", default-features = false } -cairo-vm-tracer = { path = "./cairo-vm-tracer", version = "2.0.0-rc0", default-features = false } +cairo-vm = { path = "./vm", version = "2.0.0-rc1", default-features = false } +cairo-vm-tracer = { path = "./cairo-vm-tracer", version = "2.0.0-rc1", default-features = false } mimalloc = { version = "0.1.37", default-features = false } num-bigint = { version = "0.4", default-features = false, features = [ "serde", From 0b30ba24485d72e88a81cf9867a1a1e3c3a7112e Mon Sep 17 00:00:00 2001 From: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:21:01 -0300 Subject: [PATCH 17/34] Update codeowners (#1879) --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 4e1812b071..4f9f94059e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @igaray @Oppen @fmoletta @juanbono @pefontana +* @igaray @Oppen @fmoletta @juanbono @pefontana @gabrielbosio From 22be18094244c45e352dd6ca624a8d32f4cf8857 Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Tue, 26 Nov 2024 11:20:42 -0300 Subject: [PATCH 18/34] Change macos-12 to macos-13 (#1883) * latest * change to macos-13 * chage to macos-15 * change to macos-13 --- .github/workflows/test_install.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_install.yml b/.github/workflows/test_install.yml index 53b32a21ef..7f56294398 100644 --- a/.github/workflows/test_install.yml +++ b/.github/workflows/test_install.yml @@ -12,7 +12,7 @@ jobs: name: "Install on ${{ matrix.os }}" strategy: matrix: - os: [ubuntu-22.04, macos-12] + os: [ubuntu-22.04, macos-13] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 From 1f71192cebdd112089d3f70400f4b0c4c886ea6f Mon Sep 17 00:00:00 2001 From: Geoffrey Mureithi Date: Mon, 2 Dec 2024 16:33:55 +0300 Subject: [PATCH 19/34] Update pip cairo-lang to 0.13.3 (#1884) * Update pip cairo-lang to 0.13.3 * Update CHANGELOG --- CHANGELOG.md | 2 ++ requirements.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e843ee992..4e04a5fcb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* chore: bump pip `cairo-lang` 0.13.3 [#1884](https://github.com/lambdaclass/cairo-vm/pull/1884) + #### [2.0.0-rc1] - 2024-11-20 * feat: add `EvalCircuit` and `TestLessThanOrEqualAddress` hints [#1843](https://github.com/lambdaclass/cairo-vm/pull/1843) diff --git a/requirements.txt b/requirements.txt index a47d1c9122..d1eb811f6d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,4 @@ bitarray==2.7.3 fastecdsa==2.3.0 sympy==1.11.1 typeguard==2.13.3 -cairo-lang==0.13.2 +cairo-lang==0.13.3 From 8f157a2eb62069edc5e381c8fe001a3a649910a1 Mon Sep 17 00:00:00 2001 From: YairVaknin-starkware <141148375+YairVaknin-starkware@users.noreply.github.com> Date: Mon, 2 Dec 2024 22:57:23 +0200 Subject: [PATCH 20/34] Changes_for_using_hint_extention_feature (#1880) * Changes_for_using_hint_extention_feature * changelog fix * remove `as_any_mut` --------- Co-authored-by: Pedro Fontana --- CHANGELOG.md | 3 +++ vm/src/types/program.rs | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e04a5fcb3..88f3e4b959 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ * chore: bump pip `cairo-lang` 0.13.3 [#1884](https://github.com/lambdaclass/cairo-vm/pull/1884) +* chore: [#1880](https://github.com/lambdaclass/cairo-vm/pull/1880): + * Refactor vm crate to make it possible to use hint extension feature for nested programs with hints. + #### [2.0.0-rc1] - 2024-11-20 * feat: add `EvalCircuit` and `TestLessThanOrEqualAddress` hints [#1843](https://github.com/lambdaclass/cairo-vm/pull/1843) diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index 477f996577..1c97580ee0 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -60,9 +60,9 @@ use arbitrary::{Arbitrary, Unstructured}; // failures. // Fields in `Program` (other than `SharedProgramData` itself) are used by the main logic. #[derive(Clone, Default, Debug, PartialEq, Eq)] -pub(crate) struct SharedProgramData { +pub struct SharedProgramData { pub(crate) data: Vec, - pub(crate) hints_collection: HintsCollection, + pub hints_collection: HintsCollection, pub(crate) main: Option, //start and end labels will only be used in proof-mode pub(crate) start: Option, @@ -70,7 +70,7 @@ pub(crate) struct SharedProgramData { pub(crate) error_message_attributes: Vec, pub(crate) instruction_locations: Option>, pub(crate) identifiers: HashMap, - pub(crate) reference_manager: Vec, + pub reference_manager: Vec, } #[cfg(feature = "test_utils")] @@ -107,13 +107,13 @@ impl<'a> Arbitrary<'a> for SharedProgramData { } #[derive(Clone, Default, Debug, PartialEq, Eq)] -pub(crate) struct HintsCollection { - hints: Vec, +pub struct HintsCollection { + pub hints: Vec, /// This maps a PC to the range of hints in `hints` that correspond to it. #[cfg(not(feature = "extensive_hints"))] pub(crate) hints_ranges: Vec, #[cfg(feature = "extensive_hints")] - pub(crate) hints_ranges: HashMap, + pub hints_ranges: HashMap, } impl HintsCollection { @@ -200,8 +200,8 @@ pub type HintRange = (usize, NonZeroUsize); #[cfg_attr(feature = "test_utils", derive(Arbitrary))] #[derive(Clone, Debug, PartialEq, Eq)] pub struct Program { - pub(crate) shared_program_data: Arc, - pub(crate) constants: HashMap, + pub shared_program_data: Arc, + pub constants: HashMap, pub(crate) builtins: Vec, } From 4e55e354479a835341b0bdcadd340cf71da576b7 Mon Sep 17 00:00:00 2001 From: Stephen Shelton Date: Mon, 2 Dec 2024 15:29:46 -0700 Subject: [PATCH 21/34] Convert relocation table to HashMap (#1862) * Convert relocation table to HashMap * Update CHANGELOG * Add documentation * Add a couple basic tests * First pass at hiding relocation table mods behind extensive_hints * fmt * Run tests only for feature = "extensive_hints" * Silence clippy warning about useless conversion * Only use Into if "extensive_hints" Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> --------- Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> --- CHANGELOG.md | 3 + .../builtin_hint_processor/segments.rs | 3 + .../cairo_1_hint_processor/dict_manager.rs | 2 +- vm/src/vm/vm_core.rs | 7 +- vm/src/vm/vm_memory/memory.rs | 148 +++++++++++++++++- 5 files changed, 159 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88f3e4b959..fee65de5ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ #### Upcoming Changes +* fix: [#1862](https://github.com/lambdaclass/cairo-vm/pull/1862): + * Use MaybeRelocatable for relocation table + * chore: bump pip `cairo-lang` 0.13.3 [#1884](https://github.com/lambdaclass/cairo-vm/pull/1884) * chore: [#1880](https://github.com/lambdaclass/cairo-vm/pull/1880): diff --git a/vm/src/hint_processor/builtin_hint_processor/segments.rs b/vm/src/hint_processor/builtin_hint_processor/segments.rs index c996c2f9b1..bc95c6c1ba 100644 --- a/vm/src/hint_processor/builtin_hint_processor/segments.rs +++ b/vm/src/hint_processor/builtin_hint_processor/segments.rs @@ -19,7 +19,10 @@ pub fn relocate_segment( ap_tracking: &ApTracking, ) -> Result<(), HintError> { let src_ptr = get_ptr_from_var_name("src_ptr", vm, ids_data, ap_tracking)?; + #[cfg(not(feature = "extensive_hints"))] let dest_ptr = get_ptr_from_var_name("dest_ptr", vm, ids_data, ap_tracking)?; + #[cfg(feature = "extensive_hints")] + let dest_ptr = crate::hint_processor::builtin_hint_processor::hint_utils::get_maybe_relocatable_from_var_name("dest_ptr", vm, ids_data, ap_tracking)?; vm.add_relocation_rule(src_ptr, dest_ptr) .map_err(HintError::Memory)?; diff --git a/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs b/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs index a82a4fa2db..f3fe2fb9a0 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/dict_manager.rs @@ -126,7 +126,7 @@ impl DictManagerExecScope { if self.use_temporary_segments { let mut prev_end = vm.add_memory_segment(); for tracker in &self.trackers { - vm.add_relocation_rule(tracker.start, prev_end)?; + vm.add_relocation_rule(tracker.start, prev_end.into())?; prev_end += (tracker.end.unwrap_or_default() - tracker.start)?; prev_end += 1; } diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index a65014a7b3..5862aee093 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -1000,6 +1000,10 @@ impl VirtualMachine { /// Add a new relocation rule. /// + /// When using feature "extensive_hints" the destination is allowed to be an Integer (via + /// MaybeRelocatable). Relocating memory to anything other than a `Relocatable` is generally + /// not useful, but it does make the implementation consistent with the pythonic version. + /// /// Will return an error if any of the following conditions are not met: /// - Source address's segment must be negative (temporary). /// - Source address's offset must be zero. @@ -1007,7 +1011,8 @@ impl VirtualMachine { pub fn add_relocation_rule( &mut self, src_ptr: Relocatable, - dst_ptr: Relocatable, + #[cfg(not(feature = "extensive_hints"))] dst_ptr: Relocatable, + #[cfg(feature = "extensive_hints")] dst_ptr: MaybeRelocatable, ) -> Result<(), MemoryError> { self.segments.memory.add_relocation_rule(src_ptr, dst_ptr) } diff --git a/vm/src/vm/vm_memory/memory.rs b/vm/src/vm/vm_memory/memory.rs index 9dbfc9a790..affd0a06d4 100644 --- a/vm/src/vm/vm_memory/memory.rs +++ b/vm/src/vm/vm_memory/memory.rs @@ -161,7 +161,10 @@ pub struct Memory { pub(crate) temp_data: Vec>, // relocation_rules's keys map to temp_data's indices and therefore begin at // zero; that is, segment_index = -1 maps to key 0, -2 to key 1... + #[cfg(not(feature = "extensive_hints"))] pub(crate) relocation_rules: HashMap, + #[cfg(feature = "extensive_hints")] + pub(crate) relocation_rules: HashMap, pub validated_addresses: AddressSet, validation_rules: Vec>, } @@ -247,6 +250,7 @@ impl Memory { } // Version of Memory.relocate_value() that doesn't require a self reference + #[cfg(not(feature = "extensive_hints"))] fn relocate_address( addr: Relocatable, relocation_rules: &HashMap, @@ -260,6 +264,23 @@ impl Memory { } Ok(addr.into()) } + #[cfg(feature = "extensive_hints")] + fn relocate_address( + addr: Relocatable, + relocation_rules: &HashMap, + ) -> Result { + if addr.segment_index < 0 { + // Adjust the segment index to begin at zero, as per the struct field's + // comment. + if let Some(x) = relocation_rules.get(&(-(addr.segment_index + 1) as usize)) { + return Ok(match x { + MaybeRelocatable::RelocatableValue(r) => (*r + addr.offset)?.into(), + MaybeRelocatable::Int(i) => i.into(), + }); + } + } + Ok(addr.into()) + } /// Relocates the memory according to the relocation rules and clears `self.relocaction_rules`. pub fn relocate_memory(&mut self) -> Result<(), MemoryError> { @@ -289,6 +310,15 @@ impl Memory { for index in (0..self.temp_data.len()).rev() { if let Some(base_addr) = self.relocation_rules.get(&index) { let data_segment = self.temp_data.remove(index); + + #[cfg(feature = "extensive_hints")] + let base_addr = match base_addr { + MaybeRelocatable::RelocatableValue(addr) => addr, + MaybeRelocatable::Int(_) => { + continue; + } + }; + // Insert the to-be relocated segment into the real memory let mut addr = *base_addr; if let Some(s) = self.data.get_mut(addr.segment_index as usize) { @@ -310,13 +340,17 @@ impl Memory { self.relocation_rules.clear(); Ok(()) } - /// Add a new relocation rule. /// + /// When using feature "extensive_hints" the destination is allowed to be an Integer (via + /// MaybeRelocatable). Relocating memory to anything other than a `Relocatable` is generally + /// not useful, but it does make the implementation consistent with the pythonic version. + /// /// Will return an error if any of the following conditions are not met: /// - Source address's segment must be negative (temporary). /// - Source address's offset must be zero. /// - There shouldn't already be relocation at the source segment. + #[cfg(not(feature = "extensive_hints"))] pub(crate) fn add_relocation_rule( &mut self, src_ptr: Relocatable, @@ -341,6 +375,31 @@ impl Memory { self.relocation_rules.insert(segment_index, dst_ptr); Ok(()) } + #[cfg(feature = "extensive_hints")] + pub(crate) fn add_relocation_rule( + &mut self, + src_ptr: Relocatable, + dst: MaybeRelocatable, + ) -> Result<(), MemoryError> { + if src_ptr.segment_index >= 0 { + return Err(MemoryError::AddressNotInTemporarySegment( + src_ptr.segment_index, + )); + } + if src_ptr.offset != 0 { + return Err(MemoryError::NonZeroOffset(src_ptr.offset)); + } + + // Adjust the segment index to begin at zero, as per the struct field's + // comment. + let segment_index = -(src_ptr.segment_index + 1) as usize; + if self.relocation_rules.contains_key(&segment_index) { + return Err(MemoryError::DuplicatedRelocation(src_ptr.segment_index)); + } + + self.relocation_rules.insert(segment_index, dst); + Ok(()) + } /// Gets the value from memory address as a Felt252 value. /// Returns an Error if the value at the memory address is missing or not a Felt252. @@ -646,6 +705,7 @@ pub(crate) trait RelocateValue<'a, Input: 'a, Output: 'a> { fn relocate_value(&self, value: Input) -> Result; } +#[cfg(not(feature = "extensive_hints"))] impl RelocateValue<'_, Relocatable, Relocatable> for Memory { fn relocate_value(&self, addr: Relocatable) -> Result { if addr.segment_index < 0 { @@ -661,6 +721,27 @@ impl RelocateValue<'_, Relocatable, Relocatable> for Memory { Ok(addr) } } +#[cfg(feature = "extensive_hints")] +impl RelocateValue<'_, Relocatable, MaybeRelocatable> for Memory { + fn relocate_value(&self, addr: Relocatable) -> Result { + if addr.segment_index < 0 { + // Adjust the segment index to begin at zero, as per the struct field's + // comment. + if let Some(x) = self + .relocation_rules + .get(&(-(addr.segment_index + 1) as usize)) + { + return Ok(match x { + MaybeRelocatable::RelocatableValue(r) => { + (*r + addr.offset).map_err(MemoryError::Math)?.into() + } + MaybeRelocatable::Int(i) => i.into(), + }); + } + } + Ok(addr.into()) + } +} impl<'a> RelocateValue<'a, &'a Felt252, &'a Felt252> for Memory { fn relocate_value(&self, value: &'a Felt252) -> Result<&'a Felt252, MemoryError> { @@ -676,7 +757,12 @@ impl<'a> RelocateValue<'a, &'a MaybeRelocatable, Cow<'a, MaybeRelocatable>> for Ok(match value { MaybeRelocatable::Int(_) => Cow::Borrowed(value), MaybeRelocatable::RelocatableValue(addr) => { - Cow::Owned(self.relocate_value(*addr)?.into()) + #[cfg(not(feature = "extensive_hints"))] + let v = self.relocate_value(*addr)?.into(); + #[cfg(feature = "extensive_hints")] + let v = self.relocate_value(*addr)?; + + Cow::Owned(v) } }) } @@ -1617,6 +1703,64 @@ mod memory_tests { ); } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg(feature = "extensive_hints")] + fn relocate_address_to_integer() { + let mut memory = Memory::new(); + memory + .add_relocation_rule((-1, 0).into(), 0.into()) + .unwrap(); + memory + .add_relocation_rule((-2, 0).into(), 42.into()) + .unwrap(); + + assert_eq!( + Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(), + MaybeRelocatable::Int(0.into()), + ); + assert_eq!( + Memory::relocate_address((-2, 0).into(), &memory.relocation_rules).unwrap(), + MaybeRelocatable::Int(42.into()), + ); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg(feature = "extensive_hints")] + fn relocate_address_integer_no_duplicates() { + let mut memory = Memory::new(); + memory + .add_relocation_rule((-1, 0).into(), 1.into()) + .unwrap(); + assert_eq!( + memory.add_relocation_rule((-1, 0).into(), 42.into()), + Err(MemoryError::DuplicatedRelocation(-1)) + ); + assert_eq!( + memory.add_relocation_rule((-1, 0).into(), (2, 0).into()), + Err(MemoryError::DuplicatedRelocation(-1)) + ); + + assert_eq!( + Memory::relocate_address((-1, 0).into(), &memory.relocation_rules).unwrap(), + MaybeRelocatable::Int(1.into()), + ); + + memory + .add_relocation_rule((-2, 0).into(), (3, 0).into()) + .unwrap(); + assert_eq!( + memory.add_relocation_rule((-2, 0).into(), 1.into()), + Err(MemoryError::DuplicatedRelocation(-2)) + ); + + assert_eq!( + Memory::relocate_address((-2, 0).into(), &memory.relocation_rules).unwrap(), + MaybeRelocatable::RelocatableValue((3, 0).into()), + ); + } + #[test] fn mark_address_as_accessed() { let mut memory = memory![((0, 0), 0)]; From 577f74498ee5b3448e5a4dea69ec4607b34c4734 Mon Sep 17 00:00:00 2001 From: Olivier Desenfans Date: Tue, 3 Dec 2024 18:08:52 +0400 Subject: [PATCH 22/34] feat: SECP related hints (#1829) * feat: secp-related hints Problem: we need an implementation of the hints used by the Starknet OS in the secp syscalls. These hints rely on private primitives in `cairo-vm` and need to be implemented here. Solution: this PR adds an implementation of all the hints that require `cairo-vm` primitives in the `cairo-vm` repository. * PR link in changelog * fix: handle unwraps in secp hints with HintError variants * add: cairo-0-secp-hints to allow enabling secp related hints * lint: clippy replace `.get(0)` with `.first()` * tests: add integration tests for cairo-0-secp hints * fix: add missing feature `cairo-0-secp-hints` in tests * fix: get the ec_cairo test running * fix: move the test programs to own dir and update Makefile * fix: remove some test remnants * fix: move cairo-0-secp-hints to special_features matrix * lint: cargo fmt * fix: remove unneeed recipes * fix: remove SECP_CAIRO0_HINTS_PROOF_TESTS * fix: remove unused error variant * fix: use div_mod_floor instead of div_rem * revert: use div_mod_floor instead of div_rem * changelog: add this PR to upcoming changes * fix: remove unnecessary newline --------- Co-authored-by: whichqua Co-authored-by: Herman Obst Demaestri --- .github/workflows/rust.yml | 5 +- CHANGELOG.md | 2 + Makefile | 9 +- .../secp_cairo0_compute_q_mod_prime.cairo | 52 ++ .../secp_cairo0_ec.cairo | 105 +++ .../secp_cairo0_ec_double_assign_new_x.cairo | 26 + .../secp_cairo0_ec_mul_by_uint256.cairo | 26 + .../secp_cairo0_get_point_from_x.cairo | 31 + .../secp_cairo0_reduce_value.cairo | 39 + .../secp_cairo0_reduce_x.cairo | 39 + vm/Cargo.toml | 1 + .../builtin_hint_processor_definition.rs | 93 +++ .../secp/cairo0_hints.rs | 671 ++++++++++++++++++ .../builtin_hint_processor/secp/ec_utils.rs | 8 +- .../builtin_hint_processor/secp/mod.rs | 2 + .../builtin_hint_processor/secp/secp_utils.rs | 7 +- .../builtin_hint_processor/secp/signature.rs | 2 + vm/src/lib.rs | 1 + vm/src/tests/cairo_run_test.rs | 68 ++ vm/src/vm/errors/hint_errors.rs | 2 + 20 files changed, 1179 insertions(+), 10 deletions(-) create mode 100644 cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_compute_q_mod_prime.cairo create mode 100644 cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec.cairo create mode 100644 cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_double_assign_new_x.cairo create mode 100644 cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_mul_by_uint256.cairo create mode 100644 cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_get_point_from_x.cairo create mode 100644 cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_value.cairo create mode 100644 cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_x.cairo create mode 100644 vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 13ecb59765..b58b6d84d8 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -323,7 +323,7 @@ jobs: strategy: fail-fast: false matrix: - special_features: ["", "extensive_hints", "mod_builtin"] + special_features: ["", "extensive_hints", "mod_builtin", "cairo-0-secp-hints"] target: [ test#1, test#2, test#3, test#4, test-no_std#1, test-no_std#2, test-no_std#3, test-no_std#4, test-wasm ] name: Run tests runs-on: ubuntu-22.04 @@ -370,7 +370,7 @@ jobs: 'test') cargo llvm-cov nextest --lcov --output-path lcov-${{ matrix.target }}-${{ matrix.special_features }}.info \ --partition count:${PARTITION}/4 \ - --workspace --features "cairo-1-hints, test_utils, ${{ matrix.special_features }}" + --workspace --features "cairo-1-hints, test_utils, ${{ matrix.special_features }}" ;; 'test-no_std') cargo llvm-cov nextest --lcov --output-path lcov-${{ matrix.target }}-${{ matrix.special_features }}.info \ @@ -844,4 +844,3 @@ jobs: - name: Run comparison run: ./vm/src/tests/compare_all_pie_outputs.sh - diff --git a/CHANGELOG.md b/CHANGELOG.md index fee65de5ed..75027597b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* feat: Implement `SECP related` hints [#1829](https://github.com/lambdaclass/cairo-vm/pull/1829) + * fix: [#1862](https://github.com/lambdaclass/cairo-vm/pull/1862): * Use MaybeRelocatable for relocation table diff --git a/Makefile b/Makefile index 49183fd314..355f87ac07 100644 --- a/Makefile +++ b/Makefile @@ -90,6 +90,10 @@ BAD_TEST_DIR=cairo_programs/bad_programs BAD_TEST_FILES:=$(wildcard $(BAD_TEST_DIR)/*.cairo) COMPILED_BAD_TESTS:=$(patsubst $(BAD_TEST_DIR)/%.cairo, $(BAD_TEST_DIR)/%.json, $(BAD_TEST_FILES)) +SECP_CAIRO0_HINTS_DIR=cairo_programs/cairo-0-secp-hints-feature +SECP_CAIRO0_HINTS_FILES:=$(wildcard $(SECP_CAIRO0_HINTS_DIR)/*.cairo) +COMPILED_SECP_CAIRO0_HINTS:=$(patsubst $(SECP_CAIRO0_HINTS_DIR)/%.cairo, $(SECP_CAIRO0_HINTS_DIR)/%.json, $(SECP_CAIRO0_HINTS_FILES)) + PRINT_TEST_DIR=cairo_programs/print_feature PRINT_TEST_FILES:=$(wildcard $(PRINT_TEST_DIR)/*.cairo) COMPILED_PRINT_TESTS:=$(patsubst $(PRINT_TEST_DIR)/%.cairo, $(PRINT_TEST_DIR)/%.json, $(PRINT_TEST_FILES)) @@ -239,7 +243,7 @@ run: check: cargo check -cairo_test_programs: $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) $(COMPILED_PRINT_TESTS) $(COMPILED_MOD_BUILTIN_TESTS) +cairo_test_programs: $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) $(COMPILED_PRINT_TESTS) $(COMPILED_MOD_BUILTIN_TESTS) $(COMPILED_SECP_CAIRO0_HINTS) cairo_proof_programs: $(COMPILED_PROOF_TESTS) $(COMPILED_MOD_BUILTIN_PROOF_TESTS) cairo_bench_programs: $(COMPILED_BENCHES) cairo_1_test_contracts: $(CAIRO_1_COMPILED_CASM_CONTRACTS) @@ -264,7 +268,7 @@ test-wasm: cairo_proof_programs cairo_test_programs # NOTE: release mode is needed to avoid "too many locals" error wasm-pack test --release --node vm --no-default-features test-extensive_hints: cairo_proof_programs cairo_test_programs - $(TEST_COMMAND) --workspace --features "test_utils, cairo-1-hints, extensive_hints" + $(TEST_COMMAND) --workspace --features "test_utils, cairo-1-hints, cairo-0-secp-hints, extensive_hints" check-fmt: cargo fmt --all -- --check @@ -344,6 +348,7 @@ clean: rm -f $(TEST_DIR)/*.pie rm -f $(BENCH_DIR)/*.json rm -f $(BAD_TEST_DIR)/*.json + rm -f $(SECP_CAIRO0_HINTS_DIR)/*.json rm -f $(PRINT_TEST_DIR)/*.json rm -f $(CAIRO_1_CONTRACTS_TEST_DIR)/*.sierra rm -f $(CAIRO_1_CONTRACTS_TEST_DIR)/*.casm diff --git a/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_compute_q_mod_prime.cairo b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_compute_q_mod_prime.cairo new file mode 100644 index 0000000000..5cee8bbf04 --- /dev/null +++ b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_compute_q_mod_prime.cairo @@ -0,0 +1,52 @@ +%builtins range_check + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, UnreducedBigInt3 + +const BASE = 2 ** 86; +const SECP_REM = 19; + +func test_q_mod_prime{range_check_ptr: felt}(val: UnreducedBigInt3) { + let q = [ap]; + %{ + from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P + from starkware.cairo.common.cairo_secp.secp_utils import pack + + q, r = divmod(pack(ids.val, PRIME), SECP256R1_P) + assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}." + ids.q = q % PRIME + %} + let q_biased = [ap + 1]; + q_biased = q + 2 ** 127, ap++; + [range_check_ptr] = q_biased, ap++; + // This implies that q is in the range [-2**127, 2**127). + + tempvar r1 = (val.d0 + q * SECP_REM) / BASE; + assert [range_check_ptr + 1] = r1 + 2 ** 127; + // This implies that r1 is in the range [-2**127, 2**127). + // Therefore, r1 * BASE is in the range [-2**213, 2**213). + // By the soundness assumption, val.d0 is in the range (-2**250, 2**250). + // This implies that r1 * BASE = val.d0 + q * SECP_REM (as integers). + + tempvar r2 = (val.d1 + r1) / BASE; + assert [range_check_ptr + 2] = r2 + 2 ** 127; + // Similarly, this implies that r2 * BASE = val.d1 + r1 (as integers). + // Therefore, r2 * BASE**2 = val.d1 * BASE + r1 * BASE. + + assert val.d2 = q * (BASE / 8) - r2; + // Similarly, this implies that q * BASE / 4 = val.d2 + r2 (as integers). + // Therefore, + // q * BASE**3 / 4 = val.d2 * BASE**2 + r2 * BASE ** 2 = + // val.d2 * BASE**2 + val.d1 * BASE + r1 * BASE = + // val.d2 * BASE**2 + val.d1 * BASE + val.d0 + q * SECP_REM = + // val + q * SECP_REM. + // Hence, val = q * (BASE**3 / 4 - SECP_REM) = q * (2**256 - SECP_REM) = q * secp256k1_prime. + + let range_check_ptr = range_check_ptr + 3; + return (); +} + +func main{range_check_ptr: felt}() { + let val = UnreducedBigInt3(0, 0, 0); + test_q_mod_prime(val); + return (); +} diff --git a/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec.cairo b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec.cairo new file mode 100644 index 0000000000..98bc7f1cfe --- /dev/null +++ b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec.cairo @@ -0,0 +1,105 @@ +%builtins range_check + +// Tests: +// - cairo0_hints::COMPUTE_Q_MOD_PRIME +// - cairo0_hints::COMPUTE_IDS_HIGH_LOW +// - cairo0_hints::SECP_DOUBLE_ASSIGN_NEW_X +// - cairo0_hints::FAST_SECP_ADD_ASSIGN_NEW_Y + +from starkware.cairo.common.secp256r1.ec import ( + EcPoint, + compute_doubling_slope, + compute_slope, + ec_double, + fast_ec_add, + ec_mul_inner, +) +from starkware.cairo.common.cairo_secp.bigint3 import BigInt3 + +func main{range_check_ptr: felt}() { + let x = BigInt3(1, 5, 10); + let y = BigInt3(2, 4, 20); + + + let point_a = EcPoint(x, y); + + let point_b = EcPoint( + BigInt3(1, 5, 10), + BigInt3(77371252455336262886226989, 77371252455336267181195259, 19342813113834066795298795), + ); + + // let (point_c) = ec_negate(EcPoint(BigInt3(156, 6545, 100010), BigInt3(1123, -1325, 910))); + let point_c = EcPoint( + BigInt3(156, 6545, 100010), + BigInt3(77371252455336262886225868, 1324, 19342813113834066795297906), + ); + + // compute_doubling_slope + let (slope_a) = compute_doubling_slope(point_b); + assert slope_a = BigInt3( + 64839545681970757313529612, 5953360968438044038987377, 13253714962539897079325475 + ); + + let (slope_b) = compute_doubling_slope( + EcPoint(BigInt3(1231, 51235643, 100000), BigInt3(77371252455, 7737125245, 19342813113)) + ); + assert slope_b = BigInt3( + 61129622008745017597879703, 29315582959606925875642332, 13600923539144215962821694 + ); + + // compute_slope + let (slope_c) = compute_slope(point_a, point_c); + assert slope_c = BigInt3( + 69736698275759322439409874, 45955733659898858347886847, 18034242868575077772302310 + ); + + let (slope_d) = compute_slope(point_c, point_b); + assert slope_d = BigInt3( + 66872739393348882319301304, 44057296979296181456999622, 6628179500048909995474229 + ); + + // ec_double + let (point_d) = ec_double(point_a); + assert point_d = EcPoint( + BigInt3(62951442591564288805558802, 32562108923955565608466346, 18605500881547971871596634), + BigInt3(32147810383256899543807670, 5175857156528420748725791, 6618806236944685895112117), + ); + + let (point_e) = ec_double( + EcPoint(BigInt3(156, 6545, 100010), BigInt3(5336262886225868, 1324, 113834066795297906)) + ); + assert point_e = EcPoint( + BigInt3(47503316700827173496989353, 17218105161352860131668522, 527908748911931938599018), + BigInt3(50964737623371959432443726, 60451660835701602854498663, 5043009036652075489876599), + ); + + // fast_ec_add + let (point_f) = fast_ec_add(point_a, point_e); + assert point_f = EcPoint( + BigInt3(29666922781464823323928071, 37719311829566792810003084, 9541551049028573381125035), + BigInt3(12938160206947174373897851, 22954464827120147659997987, 2690642098017756659925259), + ); + + let (point_g) = fast_ec_add( + EcPoint(BigInt3(89712, 56, 7348489324), BigInt3(980126, 10, 8793)), + EcPoint(BigInt3(16451, 5967, 2171381), BigInt3(12364564, 123654, 193)), + ); + assert point_g = EcPoint( + BigInt3(14771767859485410664249539, 62406103981610765545970487, 8912032684309792565082157), + BigInt3(25591125893919304137822981, 54543895003572926651874352, 18968003584818937876851951), + ); + + // ec_mul_inner + let (pow2, res) = ec_mul_inner( + EcPoint( + BigInt3(65162296, 359657, 04862662171381), BigInt3(5166641367474701, 63029418, 793) + ), + 123, + 298, + ); + assert pow2 = EcPoint( + BigInt3(73356165220405599685396595, 44054642183803477920871071, 5138516367480965019117743), + BigInt3(40256732918865941543909206, 68107624737772931608959283, 1842118797516663063623771), + ); + return (); +} diff --git a/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_double_assign_new_x.cairo b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_double_assign_new_x.cairo new file mode 100644 index 0000000000..15deaca336 --- /dev/null +++ b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_double_assign_new_x.cairo @@ -0,0 +1,26 @@ +%builtins range_check + +from starkware.cairo.common.secp256r1.ec import ( + EcPoint, + ec_double +) +from starkware.cairo.common.cairo_secp.bigint import BigInt3 + +func main{range_check_ptr}() { + let x = BigInt3(235, 522, 111); + let y = BigInt3(1323, 15124, 796759); + + let point = EcPoint(x, y); + + let (r) = ec_double(point); + + assert r.x.d0 = 64413149096815403908768532; + assert r.x.d1 = 28841630551789071202278393; + assert r.x.d2 = 11527965423300397026710769; + + assert r.y.d0 = 6162628527473476058419904; + assert r.y.d1 = 69076668518034904023852368; + assert r.y.d2 = 10886445027049641070037760; + + return (); +} diff --git a/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_mul_by_uint256.cairo b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_mul_by_uint256.cairo new file mode 100644 index 0000000000..4e6a939e0b --- /dev/null +++ b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_mul_by_uint256.cairo @@ -0,0 +1,26 @@ +%builtins range_check + +from starkware.cairo.common.secp256r1.ec import ( + EcPoint, + ec_mul_by_uint256 +) +from starkware.cairo.common.uint256 import Uint256 +from starkware.cairo.common.cairo_secp.bigint import BigInt3 + +func main{range_check_ptr: felt}() { + let x = BigInt3(235, 522, 111); + let y = BigInt3(1323, 15124, 796759); + + let point = EcPoint(x, y); + + let scalar = Uint256( + 143186476941636880901214103594843510573, 124026708105846590725274683684370988502 + ); + let (res) = ec_mul_by_uint256(point, scalar); + + assert res = EcPoint( + BigInt3(31454759005629465428788733, 35370111304581841775514461, 13535495107675380502530193), + BigInt3(18078210390106977421552565, 53503834862379828768870254, 3887397808398301655656699), + ); + return (); +} diff --git a/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_get_point_from_x.cairo b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_get_point_from_x.cairo new file mode 100644 index 0000000000..8ac143a75b --- /dev/null +++ b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_get_point_from_x.cairo @@ -0,0 +1,31 @@ +%builtins range_check + +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_secp.bigint3 import BigInt3 +from starkware.cairo.common.cairo_secp.ec_point import EcPoint +from starkware.cairo.common.secp256r1.ec import ( + try_get_point_from_x +) +from starkware.cairo.common.uint256 import Uint256 + + +func main{range_check_ptr: felt}() { + let zero = BigInt3( + 0, 0, 0 + ); + let result: EcPoint* = alloc(); + let (is_on_curve) = try_get_point_from_x(zero, 0, result); + assert is_on_curve = 1; + + let x = BigInt3(512,2412,133); + let result: EcPoint* = alloc(); + let (is_on_curve) = try_get_point_from_x(x, 1, result); + assert is_on_curve = 1; + + let x = BigInt3(64,0,6546); + + let result: EcPoint* = alloc(); + let (is_on_curve) = try_get_point_from_x(x, 1, result); + assert is_on_curve = 0; + return (); +} diff --git a/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_value.cairo b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_value.cairo new file mode 100644 index 0000000000..15f8771f64 --- /dev/null +++ b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_value.cairo @@ -0,0 +1,39 @@ +%builtins range_check + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, UnreducedBigInt3 + +func reduce_value{range_check_ptr}(x: UnreducedBigInt3) -> (res: BigInt3) { + %{ + from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P + from starkware.cairo.common.cairo_secp.secp_utils import pack + value = pack(ids.x, PRIME) % SECP256R1_P + %} + let (res) = nondet_bigint3(); + return (res=res); +} + +func test_reduce_value{range_check_ptr: felt}() { + let x = UnreducedBigInt3(0, 0, 0); + let (reduce_a) = reduce_value(x); + assert reduce_a = BigInt3( + 0, 0, 0 + ); + + let y = UnreducedBigInt3(12354, 745634534, 81298789312879123); + let (reduce_b) = reduce_value(y); + assert reduce_b = BigInt3( + 12354, 745634534, 81298789312879123 + ); + + let z = UnreducedBigInt3(12354812987893128791212331231233, 7453123123123123312634534, 8129224990312325879); + let (reduce_c) = reduce_value(z); + assert reduce_c = BigInt3( + 16653320122975184709085185, 7453123123123123312794216, 8129224990312325879 + ); + return (); +} + +func main{range_check_ptr: felt}() { + test_reduce_value(); + return (); +} diff --git a/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_x.cairo b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_x.cairo new file mode 100644 index 0000000000..fa9865c520 --- /dev/null +++ b/cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_x.cairo @@ -0,0 +1,39 @@ +%builtins range_check + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, UnreducedBigInt3 + +func reduce_x{range_check_ptr}(x: UnreducedBigInt3) -> (res: BigInt3) { + %{ + from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P + from starkware.cairo.common.cairo_secp.secp_utils import pack + value = pack(ids.x, PRIME) % SECP256R1_P + %} + let (res) = nondet_bigint3(); + return (res=res); +} + +func test_reduce_x{range_check_ptr: felt}() { + let x = UnreducedBigInt3(0, 0, 0); + let (reduce_a) = reduce_x(x); + assert reduce_a = BigInt3( + 0, 0, 0 + ); + + let y = UnreducedBigInt3(12354, 745634534, 81298789312879123); + let (reduce_b) = reduce_x(y); + assert reduce_b = BigInt3( + 12354, 745634534, 81298789312879123 + ); + + let z = UnreducedBigInt3(12354812987893128791212331231233, 7453123123123123312634534, 8129224990312325879); + let (reduce_c) = reduce_x(z); + assert reduce_c = BigInt3( + 16653320122975184709085185, 7453123123123123312794216, 8129224990312325879 + ); + return (); +} + +func main{range_check_ptr: felt}() { + test_reduce_x(); + return (); +} diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 07bcde08cd..a900717c35 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -29,6 +29,7 @@ cairo-1-hints = [ ] tracer = [] mod_builtin = [] +cairo-0-secp-hints = [] # Note that these features are not retro-compatible with the cairo Python VM. test_utils = ["std", "dep:arbitrary", "starknet-types-core/arbitrary", "starknet-types-core/std"] # This feature will reference every test-oriented feature diff --git a/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index fcc6ad0dcc..15c8318b15 100644 --- a/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "cairo-0-secp-hints")] +use super::secp::cairo0_hints; use super::{ blake2s_utils::finalize_blake2s_v3, ec_recover::{ @@ -874,6 +876,97 @@ impl HintProcessorLogic for BuiltinHintProcessor { constants, exec_scopes, ), + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::COMPUTE_Q_MOD_PRIME => cairo0_hints::compute_q_mod_prime( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::COMPUTE_IDS_HIGH_LOW => cairo0_hints::compute_ids_high_low( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::SECP_DOUBLE_ASSIGN_NEW_X => cairo0_hints::secp_double_assign_new_x( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::FAST_SECP_ADD_ASSIGN_NEW_Y => cairo0_hints::fast_secp_add_assign_new_y( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::COMPUTE_VALUE_DIV_MOD => cairo0_hints::compute_value_div_mod( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::GENERATE_NIBBLES => cairo0_hints::generate_nibbles( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::WRITE_NIBBLES_TO_MEM => cairo0_hints::write_nibbles_to_mem( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::IS_ON_CURVE_2 => cairo0_hints::is_on_curve_2( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::SECP_R1_GET_POINT_FROM_X => cairo0_hints::r1_get_point_from_x( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::SECP_REDUCE => cairo0_hints::reduce_value( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + #[cfg(feature = "cairo-0-secp-hints")] + cairo0_hints::SECP_REDUCE_X => cairo0_hints::reduce_x( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + code => Err(HintError::UnknownHint(code.to_string().into_boxed_str())), } } diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs b/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs new file mode 100644 index 0000000000..6fec9cb10f --- /dev/null +++ b/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs @@ -0,0 +1,671 @@ +use crate::stdlib::{ + collections::HashMap, + ops::Deref, + ops::{Add, Mul, Rem}, + prelude::*, +}; + +use crate::hint_processor::builtin_hint_processor::hint_utils::{ + get_constant_from_var_name, get_integer_from_var_name, insert_value_from_var_name, +}; +use crate::hint_processor::builtin_hint_processor::uint256_utils::Uint256; +use crate::hint_processor::hint_processor_definition::HintReference; +use crate::math_utils::{div_mod, signed_felt}; +use crate::serde::deserialize_program::ApTracking; +use crate::types::errors::math_errors::MathError; +use crate::types::exec_scope::ExecutionScopes; +use crate::vm::errors::hint_errors::HintError; +use crate::vm::vm_core::VirtualMachine; +use crate::Felt252; +use num_bigint::{BigInt, BigUint}; +use num_integer::Integer; +use num_traits::One; +use num_traits::Zero; + +use super::bigint_utils::{BigInt3, Uint384}; +use super::ec_utils::EcPoint; +use super::secp_utils::{SECP256R1_ALPHA, SECP256R1_B, SECP256R1_P}; + +pub const SECP_REDUCE: &str = r#"from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P +from starkware.cairo.common.cairo_secp.secp_utils import pack +value = pack(ids.x, PRIME) % SECP256R1_P"#; +pub fn reduce_value( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + let x = Uint384::from_var_name("x", vm, ids_data, ap_tracking)?.pack86(); + exec_scopes.insert_value("value", x.mod_floor(&SECP256R1_P)); + Ok(()) +} + +pub const SECP_REDUCE_X: &str = r#"from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P +from starkware.cairo.common.cairo_secp.secp_utils import pack + +x = pack(ids.x, PRIME) % SECP256R1_P"#; +pub fn reduce_x( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + let x = Uint384::from_var_name("x", vm, ids_data, ap_tracking)?.pack86(); + exec_scopes.insert_value("x", x.mod_floor(&SECP256R1_P)); + Ok(()) +} + +pub const COMPUTE_Q_MOD_PRIME: &str = r#"from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P +from starkware.cairo.common.cairo_secp.secp_utils import pack + +q, r = divmod(pack(ids.val, PRIME), SECP256R1_P) +assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}." +ids.q = q % PRIME"#; +pub fn compute_q_mod_prime( + vm: &mut VirtualMachine, + _exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + let val = Uint384::from_var_name("val", vm, ids_data, ap_tracking)?.pack86(); + let (q, r) = val.div_mod_floor(&SECP256R1_P); + if !r.is_zero() { + return Err(HintError::SecpVerifyZero(Box::new(val))); + } + insert_value_from_var_name("q", Felt252::from(&q), vm, ids_data, ap_tracking)?; + Ok(()) +} + +pub const COMPUTE_IDS_HIGH_LOW: &str = r#"from starkware.cairo.common.math_utils import as_int + +# Correctness check. +value = as_int(ids.value, PRIME) % PRIME +assert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**165).' + +# Calculation for the assertion. +ids.high, ids.low = divmod(ids.value, ids.SHIFT)"#; +pub fn compute_ids_high_low( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + constants: &HashMap, +) -> Result<(), HintError> { + exec_scopes.insert_value::("SECP256R1_P", SECP256R1_P.clone()); + + const UPPER_BOUND: &str = "starkware.cairo.common.math.assert_250_bit.UPPER_BOUND"; + const SHIFT: &str = "starkware.cairo.common.math.assert_250_bit.SHIFT"; + + let upper_bound = constants + .get(UPPER_BOUND) + .map_or_else(|| get_constant_from_var_name("UPPER_BOUND", constants), Ok)?; + let shift = constants + .get(SHIFT) + .map_or_else(|| get_constant_from_var_name("SHIFT", constants), Ok)?; + let value = Felt252::from(&signed_felt(get_integer_from_var_name( + "value", + vm, + ids_data, + ap_tracking, + )?)); + if &value > upper_bound { + return Err(HintError::ValueOutside250BitRange(Box::new(value))); + } + + let (high, low) = value.div_rem(&shift.try_into().map_err(|_| MathError::DividedByZero)?); + insert_value_from_var_name("high", high, vm, ids_data, ap_tracking)?; + insert_value_from_var_name("low", low, vm, ids_data, ap_tracking)?; + Ok(()) +} + +pub const SECP_R1_GET_POINT_FROM_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP256R1, pack +from starkware.python.math_utils import y_squared_from_x + +y_square_int = y_squared_from_x( + x=pack(ids.x, SECP256R1.prime), + alpha=SECP256R1.alpha, + beta=SECP256R1.beta, + field_prime=SECP256R1.prime, +) + +# Note that (y_square_int ** ((SECP256R1.prime + 1) / 4)) ** 2 = +# = y_square_int ** ((SECP256R1.prime + 1) / 2) = +# = y_square_int ** ((SECP256R1.prime - 1) / 2 + 1) = +# = y_square_int * y_square_int ** ((SECP256R1.prime - 1) / 2) = y_square_int * {+/-}1. +y = pow(y_square_int, (SECP256R1.prime + 1) // 4, SECP256R1.prime) + +# We need to decide whether to take y or prime - y. +if ids.v % 2 == y % 2: + value = y +else: + value = (-y) % SECP256R1.prime"#; + +pub fn r1_get_point_from_x( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + exec_scopes.insert_value::("SECP256R1_P", SECP256R1_P.clone()); + + // def y_squared_from_x(x: int, alpha: int, beta: int, field_prime: int) -> int: + // """ + // Computes y^2 using the curve equation: + // y^2 = x^3 + alpha * x + beta (mod field_prime) + // """ + // return (pow(x, 3, field_prime) + alpha * x + beta) % field_prime + fn y_squared_from_x(x: &BigInt, alpha: &BigInt, beta: &BigInt, field_prime: &BigInt) -> BigInt { + // Compute x^3 (mod field_prime) + let x_cubed = x.modpow(&BigInt::from(3), field_prime); + + // Compute alpha * x + let alpha_x = alpha.mul(x); + + // Compute y^2 = (x^3 + alpha * x + beta) % field_prime + x_cubed.add(&alpha_x).add(beta).rem(field_prime) + } + + // prime = curve.prime + // y_squared = y_squared_from_x( + // x=x, + // alpha=curve.alpha, + // beta=curve.beta, + // field_prime=prime, + // ) + + // y = pow(y_squared, (prime + 1) // 4, prime) + // if (y & 1) != request.y_parity: + // y = (-y) % prime + + let x = Uint384::from_var_name("x", vm, ids_data, ap_tracking)? + .pack86() + .mod_floor(&SECP256R1_P); + + let y_square_int = y_squared_from_x(&x, &SECP256R1_ALPHA, &SECP256R1_B, &SECP256R1_P); + exec_scopes.insert_value::("y_square_int", y_square_int.clone()); + + // Calculate (prime + 1) // 4 + let exp = (SECP256R1_P.to_owned() + BigInt::one()).div_floor(&BigInt::from(4)); + // Calculate pow(y_square_int, exp, prime) + let y = y_square_int.modpow(&exp, &SECP256R1_P); + exec_scopes.insert_value::("y", y.clone()); + + let v = get_integer_from_var_name("v", vm, ids_data, ap_tracking)?.to_biguint(); + if v.is_even() == y.is_even() { + exec_scopes.insert_value("value", y); + } else { + let value = (-y).mod_floor(&SECP256R1_P); + exec_scopes.insert_value("value", value); + } + Ok(()) +} + +pub const IS_ON_CURVE_2: &str = r#"ids.is_on_curve = (y * y) % SECP256R1.prime == y_square_int"#; + +pub fn is_on_curve_2( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + let y: BigInt = exec_scopes.get("y")?; + let y_square_int: BigInt = exec_scopes.get("y_square_int")?; + + let is_on_curve = ((y.pow(2)) % SECP256R1_P.to_owned()) == y_square_int; + insert_value_from_var_name( + "is_on_curve", + Felt252::from(is_on_curve), + vm, + ids_data, + ap_tracking, + )?; + + Ok(()) +} + +pub const SECP_DOUBLE_ASSIGN_NEW_X: &str = r#"from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P +from starkware.cairo.common.cairo_secp.secp_utils import pack + +slope = pack(ids.slope, SECP256R1_P) +x = pack(ids.point.x, SECP256R1_P) +y = pack(ids.point.y, SECP256R1_P) + +value = new_x = (pow(slope, 2, SECP256R1_P) - 2 * x) % SECP256R1_P"#; + +pub fn secp_double_assign_new_x( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + exec_scopes.insert_value::("SECP256R1_P", SECP256R1_P.clone()); + //ids.slope + let slope = BigInt3::from_var_name("slope", vm, ids_data, ap_tracking)?; + //ids.point + let point = EcPoint::from_var_name("point", vm, ids_data, ap_tracking)?; + + let slope = slope.pack86().mod_floor(&SECP256R1_P); + let x = point.x.pack86().mod_floor(&SECP256R1_P); + let y = point.y.pack86().mod_floor(&SECP256R1_P); + + let value = + (slope.modpow(&(2usize.into()), &SECP256R1_P) - (&x << 1u32)).mod_floor(&SECP256R1_P); + + //Assign variables to vm scope + exec_scopes.insert_value("slope", slope); + exec_scopes.insert_value("x", x); + exec_scopes.insert_value("y", y); + exec_scopes.insert_value("value", value.clone()); + exec_scopes.insert_value("new_x", value); + Ok(()) +} + +pub const GENERATE_NIBBLES: &str = r#"num = (ids.scalar.high << 128) + ids.scalar.low +nibbles = [(num >> i) & 0xf for i in range(0, 256, 4)] +ids.first_nibble = nibbles.pop() +ids.last_nibble = nibbles[0]"#; +pub fn generate_nibbles( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + let num = Uint256::from_var_name("scalar", vm, ids_data, ap_tracking)?.pack(); + + // Generate nibbles + let mut nibbles: Vec = (0..256) + .step_by(4) + .map(|i| ((&num >> i) & BigUint::from(0xfu8))) + .map(|s: BigUint| s.into()) + .collect(); + + // ids.first_nibble = nibbles.pop() + let first_nibble = nibbles.pop().ok_or(HintError::EmptyNibbles)?; + + insert_value_from_var_name("first_nibble", first_nibble, vm, ids_data, ap_tracking)?; + + // ids.last_nibble = nibbles[0] + let last_nibble = *nibbles.first().ok_or(HintError::EmptyNibbles)?; + insert_value_from_var_name("last_nibble", last_nibble, vm, ids_data, ap_tracking)?; + exec_scopes.insert_value("nibbles", nibbles); + Ok(()) +} + +pub const FAST_SECP_ADD_ASSIGN_NEW_Y: &str = + r#"value = new_y = (slope * (x - new_x) - y) % SECP256R1_P"#; +pub fn fast_secp_add_assign_new_y( + _vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _ids_data: &HashMap, + _ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + //Get variables from vm scope + let (slope, x, new_x, y, secp_p) = ( + exec_scopes.get::("slope")?, + exec_scopes.get::("x")?, + exec_scopes.get::("new_x")?, + exec_scopes.get::("y")?, + SECP256R1_P.deref(), + ); + let value = (slope * (x - new_x) - y).mod_floor(secp_p); + exec_scopes.insert_value("value", value.clone()); + exec_scopes.insert_value("new_y", value); + + Ok(()) +} + +pub const WRITE_NIBBLES_TO_MEM: &str = r#"memory[fp + 0] = to_felt_or_relocatable(nibbles.pop())"#; + +pub fn write_nibbles_to_mem( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _ids_data: &HashMap, + _ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + let nibbles: &mut Vec = exec_scopes.get_mut_list_ref("nibbles")?; + let nibble = nibbles.pop().ok_or(HintError::EmptyNibbles)?; + vm.insert_value((vm.get_fp() + 0)?, nibble)?; + + Ok(()) +} + +pub const COMPUTE_VALUE_DIV_MOD: &str = r#"from starkware.python.math_utils import div_mod + +value = div_mod(1, x, SECP256R1_P)"#; +pub fn compute_value_div_mod( + _vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + _ids_data: &HashMap, + _ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + //Get variables from vm scope + let x = exec_scopes.get_ref::("x")?; + + let value = div_mod(&BigInt::one(), x, &SECP256R1_P)?; + exec_scopes.insert_value("value", value); + + Ok(()) +} + +#[cfg(test)] +mod tests { + + use assert_matches::assert_matches; + + use crate::utils::test_utils::*; + + use super::*; + + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::*; + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_is_on_curve_2() { + let mut vm = VirtualMachine::new(false); + vm.set_fp(1); + let ids_data = non_continuous_ids_data![("is_on_curve", -1)]; + vm.segments = segments![((1, 0), 1)]; + let ap_tracking = ApTracking::default(); + + let mut exec_scopes = ExecutionScopes::new(); + + let y = BigInt::from(1234); + let y_square_int = y.clone() * y.clone(); + + exec_scopes.insert_value("y", y); + exec_scopes.insert_value("y_square_int", y_square_int); + + is_on_curve_2( + &mut vm, + &mut exec_scopes, + &ids_data, + &ap_tracking, + &Default::default(), + ) + .expect("is_on_curve2() failed"); + + let is_on_curve: Felt252 = + get_integer_from_var_name("is_on_curve", &vm, &ids_data, &ap_tracking) + .expect("is_on_curve2 should be put in ids_data"); + assert_eq!(is_on_curve, 1.into()); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_compute_q_mod_prime() { + let mut vm = VirtualMachine::new(false); + + let ap_tracking = ApTracking::default(); + + let mut exec_scopes = ExecutionScopes::new(); + + vm.run_context.fp = 9; + //Create hint data + let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)]; + vm.segments = segments![((1, 4), 0), ((1, 5), 0), ((1, 6), 0)]; + compute_q_mod_prime( + &mut vm, + &mut exec_scopes, + &ids_data, + &ap_tracking, + &Default::default(), + ) + .expect("compute_q_mod_prime() failed"); + + let q: Felt252 = get_integer_from_var_name("q", &vm, &ids_data, &ap_tracking) + .expect("compute_q_mod_prime should have put 'q' in ids_data"); + assert_eq!(q, Felt252::from(0)); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_compute_ids_high_low() { + let mut vm = VirtualMachine::new(false); + + let value = BigInt::from(25); + let shift = BigInt::from(12); + + vm.set_fp(14); + let ids_data = non_continuous_ids_data![ + ("UPPER_BOUND", -14), + ("value", -11), + ("high", -8), + ("low", -5), + ("SHIFT", -2) + ]; + + vm.segments = segments!( + //UPPER_BOUND + ((1, 0), 18446744069414584321), + ((1, 1), 0), + ((1, 2), 0), + //value + ((1, 3), 25), + ((1, 4), 0), + ((1, 5), 0), + //high + ((1, 6), 2), + ((1, 7), 0), + ((1, 8), 0), + //low + ((1, 9), 1), + ((1, 10), 0), + ((1, 11), 0), + //SHIFT + ((1, 12), 12), + ((1, 13), 0), + ((1, 14), 0) + ); + + let ap_tracking = ApTracking::default(); + + let mut exec_scopes = ExecutionScopes::new(); + + let constants = HashMap::from([ + ( + "UPPER_BOUND".to_string(), + Felt252::from(18446744069414584321_u128), + ), + ("SHIFT".to_string(), Felt252::from(12)), + ]); + compute_ids_high_low( + &mut vm, + &mut exec_scopes, + &ids_data, + &ap_tracking, + &constants, + ) + .expect("compute_ids_high_low() failed"); + + let high: Felt252 = get_integer_from_var_name("high", &vm, &ids_data, &ap_tracking) + .expect("compute_ids_high_low should have put 'high' in ids_data"); + let low: Felt252 = get_integer_from_var_name("low", &vm, &ids_data, &ap_tracking) + .expect("compute_ids_high_low should have put 'low' in ids_data"); + + let (expected_high, expected_low) = value.div_rem(&shift); + assert_eq!(high, Felt252::from(expected_high)); + assert_eq!(low, Felt252::from(expected_low)); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_r1_get_point_from_x() { + let mut vm = VirtualMachine::new(false); + vm.set_fp(10); + + let ids_data = non_continuous_ids_data![("x", -10), ("v", -7)]; + vm.segments = segments!( + // X + ((1, 0), 18446744069414584321), + ((1, 1), 0), + ((1, 2), 0), + // v + ((1, 3), 1), + ((1, 4), 0), + ((1, 5), 0), + ); + let ap_tracking = ApTracking::default(); + + let mut exec_scopes = ExecutionScopes::new(); + + let x = BigInt::from(18446744069414584321u128); // Example x value + let v = BigInt::from(1); // Example v value (must be 0 or 1 for even/odd check) + + let constants = HashMap::new(); + + r1_get_point_from_x( + &mut vm, + &mut exec_scopes, + &ids_data, + &ap_tracking, + &constants, + ) + .expect("calculate_value() failed"); + + let value: BigInt = exec_scopes + .get("value") + .expect("value should be calculated and stored in exec_scopes"); + + // Compute y_squared_from_x(x) + let y_square_int = (x.modpow(&BigInt::from(3), &SECP256R1_P) + + SECP256R1_ALPHA.deref() * &x + + SECP256R1_B.deref()) + .mod_floor(&SECP256R1_P); + + // Calculate y = pow(y_square_int, (SECP256R1_P + 1) // 4, SECP256R1_P) + let exp = (SECP256R1_P.deref() + BigInt::one()).div_floor(&BigInt::from(4)); + let y = y_square_int.modpow(&exp, &SECP256R1_P); + + // Determine the expected value based on the parity of v and y + let expected_value = if v.is_even() == y.is_even() { + y + } else { + (-y).mod_floor(&SECP256R1_P) + }; + + assert_eq!(value, expected_value); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_reduce_value() { + let mut vm = VirtualMachine::new(false); + + //Initialize fp + vm.run_context.fp = 10; + + //Create hint data + let ids_data = non_continuous_ids_data![("x", -5)]; + + vm.segments = segments![ + ( + (1, 5), + ( + "1113660525233188137217661511617697775365785011829423399545361443", + 10 + ) + ), + ( + (1, 6), + ( + "1243997169368861650657124871657865626433458458266748922940703512", + 10 + ) + ), + ( + (1, 7), + ( + "1484456708474143440067316914074363277495967516029110959982060577", + 10 + ) + ) + ]; + + let ap_tracking = ApTracking::default(); + + let mut exec_scopes = ExecutionScopes::new(); + + reduce_value( + &mut vm, + &mut exec_scopes, + &ids_data, + &ap_tracking, + &Default::default(), + ) + .expect("reduce_value() failed"); + + assert_matches!( + exec_scopes.get::("value"), + Ok(x) if x == bigint_str!( + "78544963828434122936060793808853327022047551513756524908970552805092599079793" + ) + ); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_reduce_x() { + let mut vm = VirtualMachine::new(false); + + //Initialize fp + vm.run_context.fp = 10; + + //Create hint data + let ids_data = non_continuous_ids_data![("x", -5)]; + + vm.segments = segments![ + ( + (1, 5), + ( + "1113660525233188137217661511617697775365785011829423399545361443", + 10 + ) + ), + ( + (1, 6), + ( + "1243997169368861650657124871657865626433458458266748922940703512", + 10 + ) + ), + ( + (1, 7), + ( + "1484456708474143440067316914074363277495967516029110959982060577", + 10 + ) + ) + ]; + + let ap_tracking = ApTracking::default(); + + let mut exec_scopes = ExecutionScopes::new(); + + reduce_x( + &mut vm, + &mut exec_scopes, + &ids_data, + &ap_tracking, + &Default::default(), + ) + .expect("x() failed"); + + assert_matches!( + exec_scopes.get::("x"), + Ok(x) if x == bigint_str!( + "78544963828434122936060793808853327022047551513756524908970552805092599079793" + ) + ); + } +} diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs index fdafd49e07..4eb99ac6d4 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs @@ -27,12 +27,12 @@ use num_traits::{One, ToPrimitive, Zero}; use super::secp_utils::SECP256R1_P; #[derive(Debug, PartialEq)] -struct EcPoint<'a> { - x: BigInt3<'a>, - y: BigInt3<'a>, +pub(crate) struct EcPoint<'a> { + pub(crate) x: BigInt3<'a>, + pub(crate) y: BigInt3<'a>, } impl EcPoint<'_> { - fn from_var_name<'a>( + pub(crate) fn from_var_name<'a>( name: &'a str, vm: &'a VirtualMachine, ids_data: &'a HashMap, diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/mod.rs b/vm/src/hint_processor/builtin_hint_processor/secp/mod.rs index bb98b7868a..c47d6e5628 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/mod.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/mod.rs @@ -1,4 +1,6 @@ pub mod bigint_utils; +#[cfg(feature = "cairo-0-secp-hints")] +pub mod cairo0_hints; pub mod ec_utils; pub mod field_utils; pub mod secp_utils; diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs index 4457c975b3..4d5ffaf8b3 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/secp_utils.rs @@ -6,7 +6,7 @@ use crate::vm::errors::hint_errors::HintError; use lazy_static::lazy_static; use num_bigint::{BigInt, BigUint}; -use num_traits::Zero; +use num_traits::{Num, Zero}; // Constants in package "starkware.cairo.common.cairo_secp.constants". pub const BASE_86: &str = "starkware.cairo.common.cairo_secp.constants.BASE"; @@ -66,6 +66,11 @@ lazy_static! { pub(crate) static ref SECP256R1_ALPHA: BigInt = BigInt::from_str( "115792089210356248762697446949407573530086143415290314195533631308867097853948" ).unwrap(); + pub(crate) static ref SECP256R1_B: BigInt = BigInt::from_str_radix( + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + 16, + ) + .unwrap(); } /* diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs b/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs index 57d72b5bba..b495ab073f 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -118,8 +118,10 @@ pub fn get_point_from_x( .pack86() .mod_floor(&SECP_P); let y_cube_int = (x_cube_int + beta).mod_floor(&SECP_P); + exec_scopes.insert_value("y_square_int", y_cube_int.clone()); // Divide by 4 let mut y = y_cube_int.modpow(&(&*SECP_P + 1_u32).shr(2_u32), &SECP_P); + exec_scopes.insert_value::("y", y.clone()); let v = get_integer_from_var_name("v", vm, ids_data, ap_tracking)?.to_bigint(); if v.is_even() != y.is_even() { diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 5d78058f13..90545d0f47 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -8,6 +8,7 @@ //! - the `skip_next_instruction()` hints; //! - implementations of [`arbitrary::Arbitrary`](https://docs.rs/arbitrary/latest/arbitrary/) for some structs. //! - `cairo-1-hints`: Enable hints that were introduced in Cairo 1. Not enabled by default. +//! - `cairo-0-secp-hints`: Enable secp hints that were introduced in Cairo 0. Not enabled by default. #![cfg_attr(docsrs, feature(doc_cfg))] #![deny(warnings)] diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index 55126c98df..f33ed945de 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -1240,3 +1240,71 @@ fn cairo_run_apply_poly_proof() { include_bytes!("../../../cairo_programs/mod_builtin_feature/proof/apply_poly.json"); run_program(program_data, true, None, None, None); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +#[cfg(feature = "cairo-0-secp-hints")] +fn cairo_run_secp_cairo0_reduce_value() { + let program_data = include_bytes!( + "../../../cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_value.json" + ); + run_program_simple(program_data.as_slice()); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +#[cfg(feature = "cairo-0-secp-hints")] +fn cairo_run_secp_cairo0_ec() { + let program_data = + include_bytes!("../../../cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec.json"); + run_program_simple(program_data.as_slice()); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +#[cfg(feature = "cairo-0-secp-hints")] +fn cairo_run_secp_cairo0_reduce_x() { + let program_data = include_bytes!( + "../../../cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_reduce_x.json" + ); + run_program_simple(program_data.as_slice()); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +#[cfg(feature = "cairo-0-secp-hints")] +fn cairo_run_secp_cairo0_get_point_from_x() { + let program_data = include_bytes!( + "../../../cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_get_point_from_x.json" + ); + run_program_simple(program_data.as_slice()); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +#[cfg(feature = "cairo-0-secp-hints")] +fn cairo_run_secp_cairo0_compute_q_mod_prime() { + let program_data = include_bytes!( + "../../../cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_compute_q_mod_prime.json" + ); + run_program_simple(program_data.as_slice()); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +#[cfg(feature = "cairo-0-secp-hints")] +fn cairo_run_secp_cairo0_ec_double_assign_new_x() { + let program_data = + include_bytes!("../../../cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_double_assign_new_x.json"); + run_program_simple(program_data.as_slice()); +} + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +#[cfg(feature = "cairo-0-secp-hints")] +fn cairo_run_secp_cairo0_ec_mul_by_uint256() { + let program_data = include_bytes!( + "../../../cairo_programs/cairo-0-secp-hints-feature/secp_cairo0_ec_mul_by_uint256.json" + ); + run_program_simple(program_data.as_slice()); +} diff --git a/vm/src/vm/errors/hint_errors.rs b/vm/src/vm/errors/hint_errors.rs index 849d38288d..4851980837 100644 --- a/vm/src/vm/errors/hint_errors.rs +++ b/vm/src/vm/errors/hint_errors.rs @@ -192,6 +192,8 @@ pub enum HintError { ExcessBalanceKeyError(Box), #[error("excess_balance_func: Failed to calculate {0}")] ExcessBalanceCalculationFailed(Box), + #[error("generate_nibbles fail: tried to read from an empty list of nibbles")] + EmptyNibbles, #[error("circuit evalution: {0}")] CircuitEvaluationFailed(Box), } From d2c056e4a89aec9901c176f056dbcc58dd4660e5 Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Tue, 3 Dec 2024 14:55:45 -0300 Subject: [PATCH 23/34] (fix) Replace div_rem with div_mod_floor (#1881) * replace div_rem with div_mod_floor * format * changelog * remove unwanted programs * clippy * fix changelog --- CHANGELOG.md | 4 + Cargo.lock | 88 +++++++++---------- .../secp/field_utils.rs | 4 +- 3 files changed, 50 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75027597b0..d208aa25aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,12 @@ #### Upcoming Changes +* fix: replace `div_rem` with `div_mod_floor` in `verify_zero` hints [#1881](https://github.com/lambdaclass/cairo-vm/pull/1881) + * feat: Implement `SECP related` hints [#1829](https://github.com/lambdaclass/cairo-vm/pull/1829) +* chore: bump pip `cairo-lang` 0.13.3 [#1884](https://github.com/lambdaclass/cairo-vm/pull/1884) + * fix: [#1862](https://github.com/lambdaclass/cairo-vm/pull/1862): * Use MaybeRelocatable for relocation table diff --git a/Cargo.lock b/Cargo.lock index 5d13555d68..b9b1aa67ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,9 +216,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-compression" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb8f1d480b0ea3783ab015936d2a55c87e219676f0c0b7dec61494043f21857" +checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" dependencies = [ "brotli", "flate2", @@ -238,7 +238,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -625,7 +625,7 @@ checksum = "ac857ec4b564712f3e16e3314e23cc0787ab1c05cdfee83f1c8f9989a6eee40f" dependencies = [ "cairo-lang-debug", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1074,7 +1074,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1146,9 +1146,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1269,7 +1269,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1461,7 +1461,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1519,7 +1519,7 @@ checksum = "43eaff6bbc0b3a878361aced5ec6a2818ee7c541c5b33b5880dfa9a86c23e9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1603,9 +1603,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -1762,13 +1762,13 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.89", ] [[package]] @@ -1814,7 +1814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "serde", ] @@ -1880,9 +1880,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a73e9fe3c49d7afb2ace819fa181a287ce54a0983eda4e0eb05c22f82ffe534" +checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" [[package]] name = "jobserver" @@ -2033,7 +2033,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -2060,9 +2060,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "microlp" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4190b5ca62abfbc95a81d57f4a8e3e3872289d656f3eeea5820b3046a1f81d4b" +checksum = "53e0c5664f9959f1c3970d523a22f0319024282cb754358c2afc7e1d45280ae3" dependencies = [ "log", "sprs", @@ -2279,7 +2279,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2365,7 +2365,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2416,15 +2416,15 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "portable-atomic-util" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90a7d5beecc52a491b54d6dd05c7a45ba1801666a5baad9fdbfc6fef8d2d206c" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ "portable-atomic", ] @@ -2465,9 +2465,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2695,7 +2695,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2797,7 +2797,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2838,7 +2838,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2849,7 +2849,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3023,7 +3023,7 @@ checksum = "bbc159a1934c7be9761c237333a57febe060ace2bc9e3b337a59a37af206d19f" dependencies = [ "starknet-curve", "starknet-ff", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3101,9 +3101,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -3163,7 +3163,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3239,7 +3239,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3367,7 +3367,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3548,7 +3548,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "wasm-bindgen-shared", ] @@ -3582,7 +3582,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3615,7 +3615,7 @@ checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3875,7 +3875,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3895,7 +3895,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/field_utils.rs index fb620f6eab..d521a4b867 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/field_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/field_utils.rs @@ -36,7 +36,7 @@ pub fn verify_zero( ) -> Result<(), HintError> { exec_scopes.insert_value("SECP_P", secp_p.clone()); let val = Uint384::from_var_name("val", vm, ids_data, ap_tracking)?.pack86(); - let (q, r) = val.div_rem(secp_p); + let (q, r) = val.div_mod_floor(secp_p); if !r.is_zero() { return Err(HintError::SecpVerifyZero(Box::new(val))); } @@ -62,7 +62,7 @@ pub fn verify_zero_with_external_const( ) -> Result<(), HintError> { let secp_p = exec_scopes.get_ref("SECP_P")?; let val = Uint384::from_var_name("val", vm, ids_data, ap_tracking)?.pack86(); - let (q, r) = val.div_rem(secp_p); + let (q, r) = val.div_mod_floor(secp_p); if !r.is_zero() { return Err(HintError::SecpVerifyZero(Box::new(val))); } From d90bcc8ea707dd3c8cc7afb999c7678e2060bff0 Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Tue, 10 Dec 2024 18:01:28 -0300 Subject: [PATCH 24/34] Add circuits to cairo 1 README (#1890) * update readme cairo1 * fix * Update cairo1-run/README.md Co-authored-by: Julian Gonzalez Calderon * Update cairo1-run/README.md Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> --------- Co-authored-by: Julian Gonzalez Calderon Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> --- cairo1-run/README.md | 12 ++++++++---- cairo1-run/trace | Bin 3145728 -> 0 bytes 2 files changed, 8 insertions(+), 4 deletions(-) delete mode 100644 cairo1-run/trace diff --git a/cairo1-run/README.md b/cairo1-run/README.md index 9271d860bb..0aa67c0b22 100644 --- a/cairo1-run/README.md +++ b/cairo1-run/README.md @@ -7,7 +7,7 @@ Once you are inside the `./cairo1-run` folder, use the CLI with the following co To install the required dependencies(cairo corelib) run ```bash -make deps +make deps ``` Now that you have the dependencies necessary to run the tests, you can run: @@ -19,7 +19,7 @@ make test To execute a Cairo 1 program (either as Cairo 1 source file or Sierra) ```bash -cargo run ../cairo_programs/cairo-1-programs/fibonacci.cairo +cargo run ../cairo_programs/cairo-1-programs/fibonacci.cairo ``` Arguments to generate the trace and memory files @@ -44,7 +44,7 @@ cargo run ../cairo_programs/cairo-1-programs/with_input/array_input_sum.cairo -- To execute all the cairo 1 programs inside `../cairo_programs/cairo-1-programs/` and generate the corresponding trace and the memory files ```bash -make run +make run ``` ## CLI argument list @@ -71,6 +71,10 @@ The cairo1-run cli supports the following optional arguments: * `--append_return_values`: Adds extra instructions to the program in order to append the return and input values to the output builtin's segment. This is the default behaviour for proof_mode. Only allows `Array` as return and input value. +## Running circuits + +Circuits in cairo 1 require to enable the `mod_builtin` feature in order for the `AddMod`, `MulMod` and `RangeCheck96` builtins to be taken into account. + # Running scarb projects As cairo1-run skips gas checks when running, you will need to add the following to your Scarb.toml to ensure that compilation is done without adding gas checks: @@ -86,7 +90,7 @@ Then run the compiled project's sierra file located at `project_name/target/proj Example: ```bash - cargo run path-to-project/target/project_name.sierra.json + cargo run path-to-project/target/project_name.sierra.json ``` # Known bugs & issues diff --git a/cairo1-run/trace b/cairo1-run/trace deleted file mode 100644 index 338056a5a3b8d72fc48da71a5079e290e5290695..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3145728 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 KKA{dc{2UJ1JxGrL From b416f80b0af39ce25358554651391c2c0a1289e8 Mon Sep 17 00:00:00 2001 From: Edgar Date: Wed, 11 Dec 2024 16:04:26 -0300 Subject: [PATCH 25/34] Update cairo-lang deps to 2.9.2 (#1891) * Update cairo-lang deps to 2.9.2 * update makefile * fix --- CHANGELOG.md | 4 ++ Cargo.lock | 113 ++++++++++++++++++++++-------------------- Cargo.toml | 16 +++--- Makefile | 2 +- README.md | 4 +- cairo1-run/Cargo.toml | 6 +-- cairo1-run/Makefile | 2 +- 7 files changed, 79 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d208aa25aa..3453dc3cd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ #### Upcoming Changes +* chore: update the cairo-vm version used in the readme + +* chore: update cairo-lang dependencies to 2.9.2 + * fix: replace `div_rem` with `div_mod_floor` in `verify_zero` hints [#1881](https://github.com/lambdaclass/cairo-vm/pull/1881) * feat: Implement `SECP related` hints [#1829](https://github.com/lambdaclass/cairo-vm/pull/1829) diff --git a/Cargo.lock b/Cargo.lock index b9b1aa67ce..a59dbd0a2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -431,9 +431,9 @@ checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cairo-lang-casm" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e0dcdb6358bb639dd729546611bd99bada94c86e3f262c3637855abea9a972" +checksum = "3929a38c1d586e35e19dbdf7798b146fba3627b308417a6d373fea8939535b6b" dependencies = [ "cairo-lang-utils", "indoc", @@ -445,9 +445,9 @@ dependencies = [ [[package]] name = "cairo-lang-compiler" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8657f5a5611f341a85e80ba0b21848fc34bfdf391bfd93df0baf4516c3e4159" +checksum = "0bed098f0c3666b3ad3a93aef6293f91fc1119bef660ce994105f6d1bc2802cf" dependencies = [ "anyhow", "cairo-lang-defs", @@ -471,18 +471,18 @@ dependencies = [ [[package]] name = "cairo-lang-debug" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0635aa554d297acefe6a35b495aba2795d0af5b7f97c4ab63829c7d62291ef41" +checksum = "d7763505dcfe15f36899074c27185bf7e3494875f63fd06350c6e3ed8d1f91d5" dependencies = [ "cairo-lang-utils", ] [[package]] name = "cairo-lang-defs" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b356e1c09898e8b8cfdd9731579d89365a13d8b4f7e717962e0cc7d125b83c" +checksum = "b4d29dc5a3cafe94ea4397d41b00cd54a9dffbe9bc3a3092a9ea617ea737bc6e" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -497,9 +497,9 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfe7c6ff96182da29012b707a3554e34a50f19cc96013ee45b0eb36dd396ec8" +checksum = "761d20ca9c3a3eb7025b2488aa6e0e5dc23c5d551dd95e83a989b5e87687f523" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -509,9 +509,9 @@ dependencies = [ [[package]] name = "cairo-lang-eq-solver" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723d244465309d5409e297b5486d62cbec06f2c47b05044414bb640e3f14caab" +checksum = "d778ec864e92c82293370a512195715b12775b05981e14065d85eb5dd3dd96b6" dependencies = [ "cairo-lang-utils", "good_lp", @@ -519,9 +519,9 @@ dependencies = [ [[package]] name = "cairo-lang-filesystem" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237030772ae5368f19a9247e1f63f753f8ad8de963477166e402f4825c0a141d" +checksum = "d9dc486c554e2df3be8e84c47e30fe55b59d2349b680fbe992bfba801ef93ff5" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -535,9 +535,9 @@ dependencies = [ [[package]] name = "cairo-lang-formatter" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b71f0eb3a36a6cb5f7f07843926783c4c17e44c9516b53171727a108782f3eb" +checksum = "675d281a3c9aa365055ce6e201d5dd91534dfccfd2929a41b7397f665c80293c" dependencies = [ "anyhow", "cairo-lang-diagnostics", @@ -555,9 +555,9 @@ dependencies = [ [[package]] name = "cairo-lang-lowering" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d095d78e2f1de499429c95655d6135a3d24c384b36d8de9f84e0aa4e07ee152" +checksum = "d880470c94f94fac08c2150bc0ce4af930b6760956a56966e47612de376d57ec" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -580,9 +580,9 @@ dependencies = [ [[package]] name = "cairo-lang-parser" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb828af7f948a3ef7fa65de14e3f639daedefb046dfefcad6e3116d2cb0f89a0" +checksum = "37e2b488f659432c8b866bf540e54ab3696a24ac0f366faac33b860c5313e78c" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -600,9 +600,9 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135a600043bf7030eacc6ebf2a609c2364d6ffeb04e1f3c809a2738f6b02c829" +checksum = "13cf34fd39a1efb997455fa38dbdb6bef489a125a2d17d77ebfea1ee580559f3" dependencies = [ "cairo-lang-defs", "cairo-lang-diagnostics", @@ -617,11 +617,17 @@ dependencies = [ "smol_str", ] +[[package]] +name = "cairo-lang-primitive-token" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123ac0ecadf31bacae77436d72b88fa9caef2b8e92c89ce63a125ae911a12fae" + [[package]] name = "cairo-lang-proc-macros" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac857ec4b564712f3e16e3314e23cc0787ab1c05cdfee83f1c8f9989a6eee40f" +checksum = "b3c4a161868276ce022c44ac500afbfa0d7d8371106feb40dfca34ea7be97503" dependencies = [ "cairo-lang-debug", "quote", @@ -630,23 +636,22 @@ dependencies = [ [[package]] name = "cairo-lang-project" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cc37b7f8889cdea631aeea3bcc70d5c86ac8fb1d98aabc83f16283d60f1643" +checksum = "fde3cc9777fff4daacbfd839a6fcefa29abd660068de47f72ac6d5883fa93ccd" dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", "serde", - "smol_str", "thiserror", "toml", ] [[package]] name = "cairo-lang-semantic" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c560cf4b4a89325d3a9594f490fffee38cf30e0990e808bb927619de9d0c973a" +checksum = "8af1f92ba601fd61a994c44d0c80d711fbb3d64b2b5a1e72905fc6f581b1fadd" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -664,15 +669,16 @@ dependencies = [ "num-bigint", "num-traits", "rust-analyzer-salsa", + "sha3", "smol_str", "toml", ] [[package]] name = "cairo-lang-sierra" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8118f55ca7d567bfc60960b445d388564d04bf48335c983b1595cb35f67a01c5" +checksum = "075c6457642ada82b32cf657d871a8545ae7a9d61c78dd5588a794c8c905abdc" dependencies = [ "anyhow", "cairo-lang-utils", @@ -697,9 +703,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2716ef8d4ce0fb700f83ed3281f3656436570e60249d41c65c79dc1ca27be002" +checksum = "b69172fe8354b1dd564bba318ccb5233aa78f70d57145b8c92a0b1cf009fa0fc" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -713,9 +719,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-gas" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a44da87a35845470c4f4c648225232a15e0875fe809045b6088464491f838b" +checksum = "42b571b73d9b02103f780aeee05dbf9a71d68d8a16341a04aa1dd581d0db3ad6" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -729,9 +735,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-generator" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bc5cf9f3965a7030a114dfe3d31d183287fbfbfbf904deaaa2468cadb936aa" +checksum = "1d3857cd98a0cb35b32cc962e70c04e6ddfcd8bf61106ac37b6cf453ec76b878" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -753,9 +759,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18b7616f1a3c41c4646094b5abf774e558428e9c1eda5d78d7b0638ec5c264e5" +checksum = "add264b156dfb01f18292282a6037070c078acca3bccde05787da1e1c997b78c" dependencies = [ "assert_matches", "cairo-lang-casm", @@ -774,9 +780,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-type-size" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871077dbc08df5d134dc3975538171c14b266ba405d1298085afdb227216f0a3" +checksum = "7bda5388ef862bc26388e999ac7ad62dd8ab3064720c3483b81fd761b051e627" dependencies = [ "cairo-lang-sierra", "cairo-lang-utils", @@ -784,9 +790,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f21804eb8931d41e258e7a393afc8ee8858308e95b3ed2e9b6b469ef68a6a50" +checksum = "32d5ed4aa48fe739f643a8c503c14aec0858c31dc73ba4e6a335b77ca7438807" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -814,9 +820,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet-classes" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2496bccd68fa0286b35b72c98439316a3a872ef7ec6d881f0dac90b17997490" +checksum = "fe691200b431e51e3d6cfa84f256a3dd2e8405f44d182843fbe124f803d085ff" dependencies = [ "cairo-lang-casm", "cairo-lang-sierra", @@ -837,12 +843,13 @@ dependencies = [ [[package]] name = "cairo-lang-syntax" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d77ea2e35d3610098ff13e373fc519aedc6a5096ed8547081aacfc104ef4422" +checksum = "0a38f1431f22a9487b9b0dd7aef098c9605fe6b8677e0f620547aa69195f7fb5" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", + "cairo-lang-primitive-token", "cairo-lang-utils", "num-bigint", "num-traits", @@ -853,9 +860,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b01d505ab26ca9ce829faf3a8dd097f5d7962d2eb8f136017a260694a6a72e8" +checksum = "fd7990586c9bb37eaa875ffeb218bdecf96f87881d03263ebf84fcd46514ca9f" dependencies = [ "genco", "xshell", @@ -863,9 +870,9 @@ dependencies = [ [[package]] name = "cairo-lang-test-utils" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb143a22f5a3510df8c4dec76e17c1e36bbcbddcd7915601f6a51a72418c454f" +checksum = "f2b76c55a742da177540d2a0eb39fa50d011998d0ccfdeae8b48ea0e2d7f077f" dependencies = [ "cairo-lang-formatter", "cairo-lang-utils", @@ -876,9 +883,9 @@ dependencies = [ [[package]] name = "cairo-lang-utils" -version = "2.9.0-dev.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35df943ebcf8e1db11ee9f4f46f843dde5b71639ca79ea0d8caa7973f91d8b12" +checksum = "ff5d7609abc99c15de7d7f90b8441b27e2bd52e930a3014c95a9b620e5d3211a" dependencies = [ "hashbrown 0.14.5", "indexmap 2.6.0", diff --git a/Cargo.toml b/Cargo.toml index cd18cb6a45..3cf6d9417d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,15 +62,15 @@ thiserror-no-std = { version = "2.0.2", default-features = false } bitvec = { version = "1", default-features = false, features = ["alloc"] } # Dependencies for cairo-1-hints feature -cairo-lang-starknet = { version = "2.9.0-dev.0", default-features = false } -cairo-lang-casm = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-starknet = { version = "2.9.2", default-features = false } +cairo-lang-casm = { version = "2.9.2", default-features = false } -cairo-lang-starknet-classes = { version = "2.9.0-dev.0", default-features = false } -cairo-lang-compiler = { version = "=2.9.0-dev.0", default-features = false } -cairo-lang-sierra-to-casm = { version = "2.9.0-dev.0", default-features = false } -cairo-lang-sierra = { version = "2.9.0-dev.0", default-features = false } -cairo-lang-runner = { version = "2.9.0-dev.0", default-features = false } -cairo-lang-utils = { version = "=2.9.0-dev.0", default-features = false } +cairo-lang-starknet-classes = { version = "2.9.2", default-features = false } +cairo-lang-compiler = { version = "=2.9.2", default-features = false } +cairo-lang-sierra-to-casm = { version = "2.9.2", default-features = false } +cairo-lang-sierra = { version = "2.9.2", default-features = false } +cairo-lang-runner = { version = "2.9.2", default-features = false } +cairo-lang-utils = { version = "=2.9.2", default-features = false } # TODO: check these dependencies for wasm compatibility ark-ff = { version = "0.4.2", default-features = false } diff --git a/Makefile b/Makefile index 355f87ac07..9a8e4f6c98 100644 --- a/Makefile +++ b/Makefile @@ -184,7 +184,7 @@ $(CAIRO_2_CONTRACTS_TEST_DIR)/%.casm: $(CAIRO_2_CONTRACTS_TEST_DIR)/%.sierra # ====================== CAIRO_2_REPO_DIR = cairo2 -CAIRO_2_VERSION = 2.9.0-dev.0 +CAIRO_2_VERSION = 2.9.2 build-cairo-2-compiler-macos: @if [ ! -d "$(CAIRO_2_REPO_DIR)" ]; then \ diff --git a/README.md b/README.md index 5056118793..1be8961632 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ You can then activate this environment by running You can add the following to your rust project's `Cargo.toml`: ```toml -cairo-vm = { version = '0.7.0'} +cairo-vm = { version = '1.0.1'} ``` ### Running cairo-vm from CLI @@ -243,7 +243,7 @@ When using cairo-vm with the Starknet devnet there are additional parameters tha &mut hint_processor, ); ``` -### Running cairo 1 programs +### Running cairo 1 programs To run a cairo 1 program enter in the folder `cd cairo1-run` and follow the [`cairo1-run documentation`](cairo1-run/README.md) diff --git a/cairo1-run/Cargo.toml b/cairo1-run/Cargo.toml index 7dc229228b..bae99d9edf 100644 --- a/cairo1-run/Cargo.toml +++ b/cairo1-run/Cargo.toml @@ -12,9 +12,9 @@ keywords.workspace = true cairo-vm = { workspace = true, features = ["std", "cairo-1-hints", "clap"] } serde_json = { workspace = true } -cairo-lang-sierra-type-size = { version = "2.9.0-dev.0", default-features = false } -cairo-lang-sierra-ap-change = { version = "2.9.0-dev.0", default-features = false } -cairo-lang-sierra-gas = { version = "2.9.0-dev.0", default-features = false } +cairo-lang-sierra-type-size = { version = "2.9.2", default-features = false } +cairo-lang-sierra-ap-change = { version = "2.9.2", default-features = false } +cairo-lang-sierra-gas = { version = "2.9.2", default-features = false } cairo-lang-starknet-classes.workspace = true cairo-lang-sierra-to-casm.workspace = true cairo-lang-compiler.workspace = true diff --git a/cairo1-run/Makefile b/cairo1-run/Makefile index 97ff8dec6e..4a4d72c69a 100644 --- a/cairo1-run/Makefile +++ b/cairo1-run/Makefile @@ -13,7 +13,7 @@ TRACES:=$(patsubst $(CAIRO_1_FOLDER)/%.cairo, $(CAIRO_1_FOLDER)/%.trace, $(CAIRO MEMORY:=$(patsubst $(CAIRO_1_FOLDER)/%.cairo, $(CAIRO_1_FOLDER)/%.memory, $(CAIRO_1_PROGRAMS)) deps: - git clone --depth=1 -b v2.9.0-dev.0 https://github.com/starkware-libs/cairo.git \ + git clone --depth=1 -b v2.9.2 https://github.com/starkware-libs/cairo.git \ && mv cairo/corelib/ . \ && rm -rf cairo/ From 43c6d50f364e463d7d7fbe37ac3602f1b10a0b10 Mon Sep 17 00:00:00 2001 From: Edgar Date: Thu, 12 Dec 2024 09:19:28 -0300 Subject: [PATCH 26/34] Update starknet-crypto to 0.7.3 (#1892) * Update starknet-crypto to 0.7.3 * try to fix wasm --- CHANGELOG.md | 2 + Cargo.lock | 44 +++--------- Cargo.toml | 6 +- vm/Cargo.toml | 2 + vm/src/program_hash.rs | 70 +++++++------------ vm/src/vm/runners/builtin_runner/signature.rs | 27 +++---- 6 files changed, 55 insertions(+), 96 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3453dc3cd1..287aef8bdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* Update starknet-crypto to 0.7.3, removing the old FieldElement completly in favour of the new Felt (that is Copy). + * chore: update the cairo-vm version used in the readme * chore: update cairo-lang dependencies to 2.9.2 diff --git a/Cargo.lock b/Cargo.lock index a59dbd0a2d..cb33f97e93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,9 +116,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "arbitrary" @@ -913,7 +913,8 @@ dependencies = [ "clap", "criterion", "generic-array", - "hashbrown 0.14.5", + "getrandom", + "hashbrown 0.15.2", "hex", "iai-callgrind", "keccak", @@ -1617,6 +1618,7 @@ dependencies = [ "allocator-api2", "equivalent", "foldhash", + "serde", ] [[package]] @@ -3004,9 +3006,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "starknet-crypto" -version = "0.6.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e2c30c01e8eb0fc913c4ee3cf676389fffc1d1182bfe5bb9670e4e72e968064" +checksum = "ded22ccf4cb9e572ce3f77de6066af53560cd2520d508876c83bb1e6b29d5cbc" dependencies = [ "crypto-bigint", "hex", @@ -3016,42 +3018,18 @@ dependencies = [ "num-traits", "rfc6979", "sha2", - "starknet-crypto-codegen", "starknet-curve", - "starknet-ff", + "starknet-types-core", "zeroize", ] -[[package]] -name = "starknet-crypto-codegen" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc159a1934c7be9761c237333a57febe060ace2bc9e3b337a59a37af206d19f" -dependencies = [ - "starknet-curve", - "starknet-ff", - "syn 2.0.89", -] - [[package]] name = "starknet-curve" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1c383518bb312751e4be80f53e8644034aa99a0afb29d7ac41b89a997db875b" -dependencies = [ - "starknet-ff", -] - -[[package]] -name = "starknet-ff" -version = "0.3.7" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abf1b44ec5b18d87c1ae5f54590ca9d0699ef4dd5b2ffa66fc97f24613ec585" +checksum = "bcde6bd74269b8161948190ace6cf069ef20ac6e79cd2ba09b320efa7500b6de" dependencies = [ - "ark-ff", - "crypto-bigint", - "getrandom", - "hex", + "starknet-types-core", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3cf6d9417d..4d003adcd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ hex = { version = "0.4.3", default-features = false } bincode = { version = "2.0.0-rc.3", default-features = false, features = [ "serde", ] } -starknet-crypto = { version = "0.6.1", default-features = false, features = [ +starknet-crypto = { version = "0.7.3", default-features = false, features = [ "signature-display", "alloc", ] } @@ -55,8 +55,8 @@ nom = { version = "7", default-features = false } sha2 = { version = "0.10.7", features = ["compress"], default-features = false } generic-array = { version = "0.14.7", default-features = false } keccak = { version = "0.1.2", default-features = false } -hashbrown = { version = "0.14.0", features = ["serde"] } -anyhow = { version = "1.0.69", default-features = false } +hashbrown = { version = "0.15.2", features = ["serde"] } +anyhow = { version = "1.0.94", default-features = false } thiserror-no-std = { version = "2.0.2", default-features = false } bitvec = { version = "1", default-features = false, features = ["alloc"] } diff --git a/vm/Cargo.toml b/vm/Cargo.toml index a900717c35..f5b35e3bdd 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -90,6 +90,8 @@ num-prime = { version = "0.4.3", features = ["big-int"] } [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test = "0.3.34" +# The js feature needs to be enabled +getrandom = { version = "*", features = ["js"]} [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] iai-callgrind = "0.3.1" diff --git a/vm/src/program_hash.rs b/vm/src/program_hash.rs index 1b0851193d..2f31fe7d9f 100644 --- a/vm/src/program_hash.rs +++ b/vm/src/program_hash.rs @@ -1,4 +1,4 @@ -use starknet_crypto::{pedersen_hash, FieldElement}; +use starknet_crypto::pedersen_hash; use crate::Felt252; @@ -7,7 +7,7 @@ use crate::types::builtin_name::BuiltinName; use crate::types::relocatable::MaybeRelocatable; use crate::vm::runners::cairo_pie::StrippedProgram; -type HashFunction = fn(&FieldElement, &FieldElement) -> FieldElement; +type HashFunction = fn(&Felt252, &Felt252) -> Felt252; #[derive(thiserror_no_std::Error, Debug)] pub enum HashChainError { @@ -27,23 +27,15 @@ pub enum ProgramHashError { #[error("Invalid program data: data contains relocatable(s)")] InvalidProgramData, - - /// Conversion from Felt252 to FieldElement failed. This is unlikely to happen - /// unless the implementation of Felt252 changes and this code is not updated properly. - #[error("Conversion from Felt252 to FieldElement failed")] - Felt252ToFieldElementConversionFailed, } /// Computes a hash chain over the data, in the following order: /// h(data[0], h(data[1], h(..., h(data[n-2], data[n-1])))). /// [cairo_lang reference](https://github.com/starkware-libs/cairo-lang/blob/efa9648f57568aad8f8a13fbf027d2de7c63c2c0/src/starkware/cairo/common/hash_chain.py#L6) -fn compute_hash_chain<'a, I>( - data: I, - hash_func: HashFunction, -) -> Result +fn compute_hash_chain<'a, I>(data: I, hash_func: HashFunction) -> Result where - I: Iterator + DoubleEndedIterator, + I: Iterator + DoubleEndedIterator, { match data.copied().rev().reduce(|x, y| hash_func(&y, &x)) { Some(result) => Ok(result), @@ -51,37 +43,27 @@ where } } -/// Creates an instance of `FieldElement` from a builtin name. +/// Creates an instance of `Felt252` from a builtin name. /// /// Converts the builtin name to bytes then attempts to create a field element from /// these bytes. This function will fail if the builtin name is over 31 characters. -fn builtin_name_to_field_element( - builtin_name: &BuiltinName, -) -> Result { +fn builtin_name_to_field_element(builtin_name: &BuiltinName) -> Result { // The Python implementation uses the builtin name without suffix - FieldElement::from_byte_slice_be(builtin_name.to_str().as_bytes()) - .map_err(|_| ProgramHashError::InvalidProgramBuiltin(builtin_name.to_str())) -} - -/// The `value: FieldElement` is `pub(crate)` and there is no accessor. -/// This function converts a `Felt252` to a `FieldElement` using a safe, albeit inefficient, -/// method. -fn felt_to_field_element(felt: &Felt252) -> Result { - let bytes = felt.to_bytes_be(); - FieldElement::from_bytes_be(&bytes) - .map_err(|_e| ProgramHashError::Felt252ToFieldElementConversionFailed) + Ok(Felt252::from_bytes_be_slice( + builtin_name.to_str().as_bytes(), + )) } -/// Converts a `MaybeRelocatable` into a `FieldElement` value. +/// Converts a `MaybeRelocatable` into a `Felt252` value. /// /// Returns `InvalidProgramData` if `maybe_relocatable` is not an integer fn maybe_relocatable_to_field_element( maybe_relocatable: &MaybeRelocatable, -) -> Result { - let felt = maybe_relocatable +) -> Result { + maybe_relocatable .get_int_ref() - .ok_or(ProgramHashError::InvalidProgramData)?; - felt_to_field_element(felt) + .copied() + .ok_or(ProgramHashError::InvalidProgramData) } /// Computes the Pedersen hash of a program. @@ -89,12 +71,12 @@ fn maybe_relocatable_to_field_element( pub fn compute_program_hash_chain( program: &StrippedProgram, bootloader_version: usize, -) -> Result { +) -> Result { let program_main = program.main; - let program_main = FieldElement::from(program_main); + let program_main = Felt252::from(program_main); // Convert builtin names to field elements - let builtin_list: Result, _> = program + let builtin_list: Result, _> = program .builtins .iter() .map(builtin_name_to_field_element) @@ -102,9 +84,9 @@ pub fn compute_program_hash_chain( let builtin_list = builtin_list?; let program_header = vec![ - FieldElement::from(bootloader_version), + Felt252::from(bootloader_version), program_main, - FieldElement::from(program.builtins.len()), + Felt252::from(program.builtins.len()), ]; let program_data: Result, _> = program @@ -115,7 +97,7 @@ pub fn compute_program_hash_chain( let program_data = program_data?; let data_chain_len = program_header.len() + builtin_list.len() + program_data.len(); - let data_chain_len_vec = vec![FieldElement::from(data_chain_len)]; + let data_chain_len_vec = vec![Felt252::from(data_chain_len)]; // Prepare a chain of iterators to feed to the hash function let data_chain = [ @@ -140,14 +122,14 @@ mod tests { #[test] fn test_compute_hash_chain() { - let data: Vec = vec![ - FieldElement::from(1u64), - FieldElement::from(2u64), - FieldElement::from(3u64), + let data: Vec = vec![ + Felt252::from(1u64), + Felt252::from(2u64), + Felt252::from(3u64), ]; let expected_hash = pedersen_hash( - &FieldElement::from(1u64), - &pedersen_hash(&FieldElement::from(2u64), &FieldElement::from(3u64)), + &Felt252::from(1u64), + &pedersen_hash(&Felt252::from(2u64), &Felt252::from(3u64)), ); let computed_hash = compute_hash_chain(data.iter(), pedersen_hash) .expect("Hash computation failed unexpectedly"); diff --git a/vm/src/vm/runners/builtin_runner/signature.rs b/vm/src/vm/runners/builtin_runner/signature.rs index 2b48bd8460..481d867b95 100644 --- a/vm/src/vm/runners/builtin_runner/signature.rs +++ b/vm/src/vm/runners/builtin_runner/signature.rs @@ -3,7 +3,6 @@ use crate::math_utils::div_mod; use crate::stdlib::{cell::RefCell, collections::HashMap, prelude::*, rc::Rc}; use crate::types::builtin_name::BuiltinName; -use crate::types::errors::math_errors::MathError; use crate::types::instance_definitions::ecdsa_instance_def::CELLS_PER_SIGNATURE; use crate::vm::errors::runner_errors::RunnerError; use crate::vm::runners::cairo_pie::BuiltinAdditionalData; @@ -22,7 +21,7 @@ use lazy_static::lazy_static; use num_bigint::{BigInt, Sign}; use num_integer::div_ceil; use num_traits::{Num, One}; -use starknet_crypto::{verify, FieldElement, Signature}; +use starknet_crypto::{verify, Signature}; lazy_static! { static ref EC_ORDER: BigInt = BigInt::from_str_radix( @@ -60,8 +59,8 @@ impl SignatureBuiltinRunner { let r_be_bytes = r.to_bytes_be(); let s_be_bytes = s.to_bytes_be(); let (r_felt, s_felt) = ( - FieldElement::from_bytes_be(&r_be_bytes).map_err(|_| MathError::ByteConversionError)?, - FieldElement::from_bytes_be(&s_be_bytes).map_err(|_| MathError::ByteConversionError)?, + Felt252::from_bytes_be(&r_be_bytes), + Felt252::from_bytes_be(&s_be_bytes), ); let signature = Signature { @@ -127,11 +126,9 @@ impl SignatureBuiltinRunner { .get(&pubkey_addr) .ok_or_else(|| MemoryError::SignatureNotFound(Box::new(pubkey_addr)))?; - let public_key = FieldElement::from_bytes_be(&pubkey.to_bytes_be()) - .map_err(|_| MathError::ByteConversionError)?; + let public_key = Felt252::from_bytes_be(&pubkey.to_bytes_be()); let (r, s) = (signature.r, signature.s); - let message = FieldElement::from_bytes_be(&msg.to_bytes_be()) - .map_err(|_| MathError::ByteConversionError)?; + let message = Felt252::from_bytes_be(&msg.to_bytes_be()); match verify(&public_key, &message, &r, &s) { Ok(true) => Ok(vec![]), _ => Err(MemoryError::InvalidSignature(Box::new(( @@ -198,10 +195,8 @@ impl SignatureBuiltinRunner { self.signatures.borrow_mut().insert( *addr, Signature { - r: FieldElement::from_bytes_be(&r.to_bytes_be()) - .map_err(|_| MathError::ByteConversionError)?, - s: FieldElement::from_bytes_be(&s.to_bytes_be()) - .map_err(|_| MathError::ByteConversionError)?, + r: Felt252::from_bytes_be(&r.to_bytes_be()), + s: Felt252::from_bytes_be(&s.to_bytes_be()), }, ); } @@ -523,8 +518,8 @@ mod tests { let signatures = HashMap::from([( Relocatable::from((4, 0)), Signature { - r: FieldElement::from_dec_str("45678").unwrap(), - s: FieldElement::from_dec_str("1239").unwrap(), + r: Felt252::from_dec_str("45678").unwrap(), + s: Felt252::from_dec_str("1239").unwrap(), }, )]); builtin.signatures = Rc::new(RefCell::new(signatures)); @@ -544,8 +539,8 @@ mod tests { let signatures = HashMap::from([( Relocatable::from((0, 0)), Signature { - r: FieldElement::from_dec_str("45678").unwrap(), - s: FieldElement::from_dec_str("1239").unwrap(), + r: Felt252::from_dec_str("45678").unwrap(), + s: Felt252::from_dec_str("1239").unwrap(), }, )]); builtin_a.signatures = Rc::new(RefCell::new(signatures)); From 3acb1cc46db246a609548f1d5a35a151fc2b286c Mon Sep 17 00:00:00 2001 From: Edgar Date: Thu, 12 Dec 2024 11:10:41 -0300 Subject: [PATCH 27/34] Bump version to v2.0.0-rc2 (#1893) --- CHANGELOG.md | 2 + Cargo.lock | 194 ++++++++++++++++++++++++--------------------------- Cargo.toml | 6 +- 3 files changed, 98 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 287aef8bdc..5305e06a95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +#### [2.0.0-rc2] - 2024-12-12 + * Update starknet-crypto to 0.7.3, removing the old FieldElement completly in favour of the new Felt (that is Copy). * chore: update the cairo-vm version used in the readme diff --git a/Cargo.lock b/Cargo.lock index cb33f97e93..55e25157a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anes" @@ -238,7 +238,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -397,9 +397,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" +checksum = "786a307d683a5bf92e6fd5fd69a7eb613751668d1d8d67d802846dfe367c62c8" dependencies = [ "memchr", "serde", @@ -425,9 +425,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cairo-lang-casm" @@ -631,7 +631,7 @@ checksum = "b3c4a161868276ce022c44ac500afbfa0d7d8371106feb40dfca34ea7be97503" dependencies = [ "cairo-lang-debug", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -888,7 +888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff5d7609abc99c15de7d7f90b8441b27e2bd52e930a3014c95a9b620e5d3211a" dependencies = [ "hashbrown 0.14.5", - "indexmap 2.6.0", + "indexmap 2.7.0", "itertools 0.12.1", "num-bigint", "num-traits", @@ -898,7 +898,7 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "2.0.0-rc1" +version = "2.0.0-rc2" dependencies = [ "anyhow", "arbitrary", @@ -943,7 +943,7 @@ dependencies = [ [[package]] name = "cairo-vm-cli" -version = "2.0.0-rc1" +version = "2.0.0-rc2" dependencies = [ "assert_matches", "bincode", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "cairo-vm-tracer" -version = "2.0.0-rc1" +version = "2.0.0-rc2" dependencies = [ "axum", "cairo-vm", @@ -977,7 +977,7 @@ dependencies = [ [[package]] name = "cairo1-run" -version = "2.0.0-rc1" +version = "2.0.0-rc2" dependencies = [ "assert_matches", "bincode", @@ -1009,9 +1009,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.1" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "jobserver", "libc", @@ -1053,9 +1053,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -1063,9 +1063,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -1082,14 +1082,14 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" @@ -1125,18 +1125,18 @@ checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" [[package]] name = "const_format" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" dependencies = [ "proc-macro2", "quote", @@ -1277,7 +1277,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1356,19 +1356,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fixedbitset" @@ -1469,7 +1469,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1527,7 +1527,7 @@ checksum = "43eaff6bbc0b3a878361aced5ec6a2818ee7c541c5b33b5880dfa9a86c23e9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1633,12 +1633,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -1653,7 +1647,7 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hint_accountant" -version = "2.0.0-rc1" +version = "2.0.0-rc2" dependencies = [ "cairo-vm", "serde", @@ -1734,7 +1728,7 @@ dependencies = [ [[package]] name = "hyper_threading" -version = "2.0.0-rc1" +version = "2.0.0-rc2" dependencies = [ "cairo-vm", "rayon", @@ -1777,7 +1771,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -1818,9 +1812,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -1849,7 +1843,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi", "libc", "windows-sys 0.52.0", ] @@ -1889,9 +1883,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -1984,9 +1978,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.164" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libm" @@ -2119,11 +2113,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -2266,29 +2259,28 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parity-scale-codec" -version = "3.7.0" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be4817d39f3272f69c59fe05d0535ae6456c2dc2fa1ba02910296c7e0a5c590" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", - "rustversion", "serde", ] [[package]] name = "parity-scale-codec-derive" -version = "3.7.0" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8781a75c6205af67215f382092b6e0a4ff3734798523e69073d4bcd294ec767b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.89", + "syn 1.0.109", ] [[package]] @@ -2339,7 +2331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.6.0", + "indexmap 2.7.0", ] [[package]] @@ -2374,7 +2366,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2589,9 +2581,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -2684,7 +2676,7 @@ version = "0.17.0-pre.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719825638c59fd26a55412a24561c7c5bcf54364c88b9a7a04ba08a6eafaba8d" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "lock_api", "oorandom", "parking_lot", @@ -2704,7 +2696,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2740,15 +2732,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2806,7 +2798,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2832,22 +2824,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2858,7 +2850,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -2972,9 +2964,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3086,9 +3078,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.89" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -3148,7 +3140,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3202,9 +3194,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -3224,14 +3216,14 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -3267,7 +3259,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -3334,9 +3326,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -3346,20 +3338,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -3378,9 +3370,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "nu-ansi-term", "sharded-slab", @@ -3533,7 +3525,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "wasm-bindgen-shared", ] @@ -3567,7 +3559,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3600,12 +3592,12 @@ checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] name = "wasm-demo" -version = "2.0.0-rc1" +version = "2.0.0-rc2" dependencies = [ "cairo-vm", "console_error_panic_hook", @@ -3860,7 +3852,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] @@ -3880,7 +3872,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.90", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4d003adcd0..767caa62f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ exclude = ["ensure-no_std"] resolver = "2" [workspace.package] -version = "2.0.0-rc1" +version = "2.0.0-rc2" edition = "2021" license = "Apache-2.0" repository = "https://github.com/lambdaclass/cairo-vm/" @@ -24,8 +24,8 @@ readme = "README.md" keywords = ["starknet", "cairo", "vm", "wasm", "no_std"] [workspace.dependencies] -cairo-vm = { path = "./vm", version = "2.0.0-rc1", default-features = false } -cairo-vm-tracer = { path = "./cairo-vm-tracer", version = "2.0.0-rc1", default-features = false } +cairo-vm = { path = "./vm", version = "2.0.0-rc2", default-features = false } +cairo-vm-tracer = { path = "./cairo-vm-tracer", version = "2.0.0-rc2", default-features = false } mimalloc = { version = "0.1.37", default-features = false } num-bigint = { version = "0.4", default-features = false, features = [ "serde", From 3f3df3eb76acf03105b0698b650db2c46dcf3fa5 Mon Sep 17 00:00:00 2001 From: Edgar Date: Thu, 12 Dec 2024 12:39:45 -0300 Subject: [PATCH 28/34] Fix getrandom wildcard dep (#1894) * fix getrandom dep * changelog --- CHANGELOG.md | 2 ++ vm/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5305e06a95..48d9402d1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ #### [2.0.0-rc2] - 2024-12-12 +* fix: Change wildcard getrandom dependency. + * Update starknet-crypto to 0.7.3, removing the old FieldElement completly in favour of the new Felt (that is Copy). * chore: update the cairo-vm version used in the readme diff --git a/vm/Cargo.toml b/vm/Cargo.toml index f5b35e3bdd..3437a30034 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -91,7 +91,7 @@ num-prime = { version = "0.4.3", features = ["big-int"] } [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test = "0.3.34" # The js feature needs to be enabled -getrandom = { version = "*", features = ["js"]} +getrandom = { version = "0.2", features = ["js"]} [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] iai-callgrind = "0.3.1" From 83bfdcf1cc971e36f7d545c1fc48655df954ecdd Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Thu, 26 Dec 2024 14:41:47 +0000 Subject: [PATCH 29/34] update cairo-lang dependencies to 2.10.0-rc.0 (#1901) --- CHANGELOG.md | 2 + Cargo.lock | 332 +++++++++++++++++------------------------- Cargo.toml | 16 +- Makefile | 2 +- cairo1-run/Cargo.toml | 6 +- cairo1-run/Makefile | 2 +- 6 files changed, 152 insertions(+), 208 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48d9402d1e..6a96385495 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ #### [2.0.0-rc2] - 2024-12-12 +* chore: update cairo-lang dependencies to 2.10.0-rc.0 + * fix: Change wildcard getrandom dependency. * Update starknet-crypto to 0.7.3, removing the old FieldElement completly in favour of the new Felt (that is Copy). diff --git a/Cargo.lock b/Cargo.lock index 55e25157a1..5f956ff02e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,9 +116,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arbitrary" @@ -238,7 +238,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -308,7 +308,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -332,7 +332,16 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ - "bit-vec", + "bit-vec 0.6.3", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec 0.8.0", ] [[package]] @@ -341,6 +350,12 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "1.3.2" @@ -431,9 +446,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cairo-lang-casm" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3929a38c1d586e35e19dbdf7798b146fba3627b308417a6d373fea8939535b6b" +checksum = "31a9a437bd4015a0f888d0de9876fd4786eb24b4e17b25c86c53980865980f9d" dependencies = [ "cairo-lang-utils", "indoc", @@ -445,9 +460,9 @@ dependencies = [ [[package]] name = "cairo-lang-compiler" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bed098f0c3666b3ad3a93aef6293f91fc1119bef660ce994105f6d1bc2802cf" +checksum = "4608693f366e8e86061c824adaca33b56bf0bd7e1cd5edc8592be7a380950322" dependencies = [ "anyhow", "cairo-lang-defs", @@ -471,18 +486,18 @@ dependencies = [ [[package]] name = "cairo-lang-debug" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7763505dcfe15f36899074c27185bf7e3494875f63fd06350c6e3ed8d1f91d5" +checksum = "4217fd373449a74efde259f8a4df501a7664f6f9c73b547c3aff632ad14feabf" dependencies = [ "cairo-lang-utils", ] [[package]] name = "cairo-lang-defs" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d29dc5a3cafe94ea4397d41b00cd54a9dffbe9bc3a3092a9ea617ea737bc6e" +checksum = "dadf2d1002c9851ea17d37b83a26bbe6f0f53d5f94ba2e477a7a6e9d498f805b" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -497,9 +512,9 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "761d20ca9c3a3eb7025b2488aa6e0e5dc23c5d551dd95e83a989b5e87687f523" +checksum = "4c4ac1831e7c14e5308a66254bcc57a8d4790f18567ef8d4d6768b39ffb955a0" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -509,9 +524,9 @@ dependencies = [ [[package]] name = "cairo-lang-eq-solver" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d778ec864e92c82293370a512195715b12775b05981e14065d85eb5dd3dd96b6" +checksum = "33c5f879bca42caef7e06f1de022d6961d36c5567db600faed8a947e2b705eaa" dependencies = [ "cairo-lang-utils", "good_lp", @@ -519,9 +534,9 @@ dependencies = [ [[package]] name = "cairo-lang-filesystem" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9dc486c554e2df3be8e84c47e30fe55b59d2349b680fbe992bfba801ef93ff5" +checksum = "c632b6d3ee5f1684f757f86e04ba9cf1daa8e4e74c6a5d6c0b7773cc4465a6c6" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -535,9 +550,9 @@ dependencies = [ [[package]] name = "cairo-lang-formatter" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675d281a3c9aa365055ce6e201d5dd91534dfccfd2929a41b7397f665c80293c" +checksum = "8295a3ddc62d8d92d942292f103de0434d622f47e936a3aea25eccc3eed88c58" dependencies = [ "anyhow", "cairo-lang-diagnostics", @@ -555,9 +570,9 @@ dependencies = [ [[package]] name = "cairo-lang-lowering" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d880470c94f94fac08c2150bc0ce4af930b6760956a56966e47612de376d57ec" +checksum = "b2a93c2644c64cfdbbe64b1bd6e13d9c6ed511950cfae2e738d228bc89dc5605" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -580,9 +595,9 @@ dependencies = [ [[package]] name = "cairo-lang-parser" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e2b488f659432c8b866bf540e54ab3696a24ac0f366faac33b860c5313e78c" +checksum = "d884d9418895fef5b8ffd7458211523ab5abf4357845938b354adfbae1089fe2" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -600,9 +615,9 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13cf34fd39a1efb997455fa38dbdb6bef489a125a2d17d77ebfea1ee580559f3" +checksum = "b224afdc76d9890edf9009fa8ffff9a91ac15614a41049d48c77c192e8c966e3" dependencies = [ "cairo-lang-defs", "cairo-lang-diagnostics", @@ -625,20 +640,20 @@ checksum = "123ac0ecadf31bacae77436d72b88fa9caef2b8e92c89ce63a125ae911a12fae" [[package]] name = "cairo-lang-proc-macros" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c4a161868276ce022c44ac500afbfa0d7d8371106feb40dfca34ea7be97503" +checksum = "0ae35a282e5f2d15f47ba6fffae5a32e8aa2f254366865339cf326e2e015b8f8" dependencies = [ "cairo-lang-debug", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] name = "cairo-lang-project" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde3cc9777fff4daacbfd839a6fcefa29abd660068de47f72ac6d5883fa93ccd" +checksum = "4da40ba380208db0b861d8b1e6e558adaa98dd0b382177b25bdb1abf8fd8d766" dependencies = [ "cairo-lang-filesystem", "cairo-lang-utils", @@ -649,9 +664,9 @@ dependencies = [ [[package]] name = "cairo-lang-semantic" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af1f92ba601fd61a994c44d0c80d711fbb3d64b2b5a1e72905fc6f581b1fadd" +checksum = "babdf14729236dfb455519d35e7e399ba73f0eaa4f1e929474d4c37dc9ef7a29" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -676,9 +691,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "075c6457642ada82b32cf657d871a8545ae7a9d61c78dd5588a794c8c905abdc" +checksum = "74c0e4951ecd88023856e0faa9fd444647d9f1ec69ca09dfa8e3aebf9d2afdef" dependencies = [ "anyhow", "cairo-lang-utils", @@ -703,9 +718,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69172fe8354b1dd564bba318ccb5233aa78f70d57145b8c92a0b1cf009fa0fc" +checksum = "9ea9c51356e603fa38fcbd4524d19e391ac25e89e64889c3a4ef849de3d1e911" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -719,9 +734,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-gas" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b571b73d9b02103f780aeee05dbf9a71d68d8a16341a04aa1dd581d0db3ad6" +checksum = "1af17244a222fd2398caaf09e909f0b584abe14c77e1b5dc8f479ef35d1e8d50" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -735,9 +750,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-generator" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3857cd98a0cb35b32cc962e70c04e6ddfcd8bf61106ac37b6cf453ec76b878" +checksum = "2368d57175b18976222f844e4dda52d0025d70ce8b2dda35e0cc96efaa9bb4a5" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -759,9 +774,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add264b156dfb01f18292282a6037070c078acca3bccde05787da1e1c997b78c" +checksum = "866e6cbba9e81bae1c2f6b8f8e718f702fee69980c3f22bdea1e4657f09a540c" dependencies = [ "assert_matches", "cairo-lang-casm", @@ -780,9 +795,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-type-size" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bda5388ef862bc26388e999ac7ad62dd8ab3064720c3483b81fd761b051e627" +checksum = "f8e797aa2f4023e984d13c5adf7068688da665328da6b055842f50fb673fb48b" dependencies = [ "cairo-lang-sierra", "cairo-lang-utils", @@ -790,9 +805,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d5ed4aa48fe739f643a8c503c14aec0858c31dc73ba4e6a335b77ca7438807" +checksum = "85c16967be9b0befaa0e21f65c9c803f8354d0db09de7adf28cdf0dc54b2c90d" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -820,9 +835,9 @@ dependencies = [ [[package]] name = "cairo-lang-starknet-classes" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe691200b431e51e3d6cfa84f256a3dd2e8405f44d182843fbe124f803d085ff" +checksum = "b0f7b0c28430c9ad477c38dba089ac5a148443bbeaa77cc3f14980de255a220e" dependencies = [ "cairo-lang-casm", "cairo-lang-sierra", @@ -843,9 +858,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a38f1431f22a9487b9b0dd7aef098c9605fe6b8677e0f620547aa69195f7fb5" +checksum = "f5adf933d378225e031200bd41c82e09cb0fde1042f5fe3f3c82d1ccd559a6f2" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -860,9 +875,9 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7990586c9bb37eaa875ffeb218bdecf96f87881d03263ebf84fcd46514ca9f" +checksum = "4b34c81e723cf05fc0655aa8527f5a2730e30b31368b1b887c3eeb50a00c81c4" dependencies = [ "genco", "xshell", @@ -870,9 +885,9 @@ dependencies = [ [[package]] name = "cairo-lang-test-utils" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b76c55a742da177540d2a0eb39fa50d011998d0ccfdeae8b48ea0e2d7f077f" +checksum = "aa7c6930beb6f221c1bc274460fca091e93c377570994b612682da30795ed74e" dependencies = [ "cairo-lang-formatter", "cairo-lang-utils", @@ -883,9 +898,9 @@ dependencies = [ [[package]] name = "cairo-lang-utils" -version = "2.9.2" +version = "2.10.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff5d7609abc99c15de7d7f90b8441b27e2bd52e930a3014c95a9b620e5d3211a" +checksum = "91b6546d9f285c7d4a2700c084f745c35e1884a1dc2e4fa54a71034cea5606aa" dependencies = [ "hashbrown 0.14.5", "indexmap 2.7.0", @@ -1009,9 +1024,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.3" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "jobserver", "libc", @@ -1082,7 +1097,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -1099,12 +1114,12 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -1208,9 +1223,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1227,9 +1242,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -1277,7 +1292,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -1394,9 +1409,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "form_urlencoded" @@ -1469,7 +1484,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -1527,7 +1542,7 @@ checksum = "43eaff6bbc0b3a878361aced5ec6a2818ee7c541c5b33b5880dfa9a86c23e9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -1705,9 +1720,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.31" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -1771,7 +1786,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -1921,7 +1936,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" dependencies = [ "ascii-canvas", - "bit-set", + "bit-set 0.5.3", "ena", "itertools 0.11.0", "lalrpop-util", @@ -1978,15 +1993,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.168" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" - -[[package]] -name = "libm" -version = "0.2.11" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libmimalloc-sys" @@ -2063,9 +2072,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "microlp" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e0c5664f9959f1c3970d523a22f0319024282cb754358c2afc7e1d45280ae3" +checksum = "a4d5845c04529928925fd1abd6776813710ad57ef41cb31958b1d35622a7d8e9" dependencies = [ "log", "sprs", @@ -2104,9 +2113,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", ] @@ -2227,14 +2236,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -2303,7 +2311,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -2366,7 +2374,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -2475,12 +2483,12 @@ dependencies = [ [[package]] name = "proptest" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" dependencies = [ - "bit-set", - "bit-vec", + "bit-set 0.8.0", + "bit-vec 0.8.0", "bitflags 2.6.0", "lazy_static", "num-traits", @@ -2501,9 +2509,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -2696,7 +2704,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -2798,7 +2806,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -2815,9 +2823,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" dependencies = [ "serde", ] @@ -2839,7 +2847,7 @@ checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -2850,14 +2858,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", "memchr", @@ -3078,9 +3086,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035" dependencies = [ "proc-macro2", "quote", @@ -3140,7 +3148,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -3216,7 +3224,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -3344,7 +3352,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -3421,9 +3429,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" @@ -3525,7 +3533,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", "wasm-bindgen-shared", ] @@ -3559,7 +3567,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3592,7 +3600,7 @@ checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -3647,22 +3655,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -3671,22 +3670,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -3695,46 +3679,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3747,48 +3713,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -3852,7 +3794,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] @@ -3872,7 +3814,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.91", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 767caa62f1..51e34e4172 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,15 +62,15 @@ thiserror-no-std = { version = "2.0.2", default-features = false } bitvec = { version = "1", default-features = false, features = ["alloc"] } # Dependencies for cairo-1-hints feature -cairo-lang-starknet = { version = "2.9.2", default-features = false } -cairo-lang-casm = { version = "2.9.2", default-features = false } +cairo-lang-starknet = { version = "2.10.0-rc.0", default-features = false } +cairo-lang-casm = { version = "2.10.0-rc.0", default-features = false } -cairo-lang-starknet-classes = { version = "2.9.2", default-features = false } -cairo-lang-compiler = { version = "=2.9.2", default-features = false } -cairo-lang-sierra-to-casm = { version = "2.9.2", default-features = false } -cairo-lang-sierra = { version = "2.9.2", default-features = false } -cairo-lang-runner = { version = "2.9.2", default-features = false } -cairo-lang-utils = { version = "=2.9.2", default-features = false } +cairo-lang-starknet-classes = { version = "2.10.0-rc.0", default-features = false } +cairo-lang-compiler = { version = "=2.10.0-rc.0", default-features = false } +cairo-lang-sierra-to-casm = { version = "2.10.0-rc.0", default-features = false } +cairo-lang-sierra = { version = "2.10.0-rc.0", default-features = false } +cairo-lang-runner = { version = "2.10.0-rc.0", default-features = false } +cairo-lang-utils = { version = "=2.10.0-rc.0", default-features = false } # TODO: check these dependencies for wasm compatibility ark-ff = { version = "0.4.2", default-features = false } diff --git a/Makefile b/Makefile index 9a8e4f6c98..7468bd0240 100644 --- a/Makefile +++ b/Makefile @@ -184,7 +184,7 @@ $(CAIRO_2_CONTRACTS_TEST_DIR)/%.casm: $(CAIRO_2_CONTRACTS_TEST_DIR)/%.sierra # ====================== CAIRO_2_REPO_DIR = cairo2 -CAIRO_2_VERSION = 2.9.2 +CAIRO_2_VERSION = 2.10.0-rc.0 build-cairo-2-compiler-macos: @if [ ! -d "$(CAIRO_2_REPO_DIR)" ]; then \ diff --git a/cairo1-run/Cargo.toml b/cairo1-run/Cargo.toml index bae99d9edf..e78ef041f9 100644 --- a/cairo1-run/Cargo.toml +++ b/cairo1-run/Cargo.toml @@ -12,9 +12,9 @@ keywords.workspace = true cairo-vm = { workspace = true, features = ["std", "cairo-1-hints", "clap"] } serde_json = { workspace = true } -cairo-lang-sierra-type-size = { version = "2.9.2", default-features = false } -cairo-lang-sierra-ap-change = { version = "2.9.2", default-features = false } -cairo-lang-sierra-gas = { version = "2.9.2", default-features = false } +cairo-lang-sierra-type-size = { version = "2.10.0-rc.0", default-features = false } +cairo-lang-sierra-ap-change = { version = "2.10.0-rc.0", default-features = false } +cairo-lang-sierra-gas = { version = "2.10.0-rc.0", default-features = false } cairo-lang-starknet-classes.workspace = true cairo-lang-sierra-to-casm.workspace = true cairo-lang-compiler.workspace = true diff --git a/cairo1-run/Makefile b/cairo1-run/Makefile index 4a4d72c69a..87777270b6 100644 --- a/cairo1-run/Makefile +++ b/cairo1-run/Makefile @@ -13,7 +13,7 @@ TRACES:=$(patsubst $(CAIRO_1_FOLDER)/%.cairo, $(CAIRO_1_FOLDER)/%.trace, $(CAIRO MEMORY:=$(patsubst $(CAIRO_1_FOLDER)/%.cairo, $(CAIRO_1_FOLDER)/%.memory, $(CAIRO_1_PROGRAMS)) deps: - git clone --depth=1 -b v2.9.2 https://github.com/starkware-libs/cairo.git \ + git clone --depth=1 -b v2.10.0-rc.0 https://github.com/starkware-libs/cairo.git \ && mv cairo/corelib/ . \ && rm -rf cairo/ From 9aa0a5feac3de846086f98530a3a961395d2da2a Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Thu, 26 Dec 2024 16:26:20 +0000 Subject: [PATCH 30/34] Bump version to v2.0.0 rc3 (#1902) * prepare release * fix changelog * fix changelog --- CHANGELOG.md | 6 ++++-- Cargo.lock | 14 +++++++------- Cargo.toml | 6 +++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a96385495..dcc5f7e6ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,11 @@ #### Upcoming Changes -#### [2.0.0-rc2] - 2024-12-12 +#### [2.0.0-rc3] - 2024-12-26 + +* chore: update cairo-lang dependencies to 2.10.0-rc.0 #[1901](https://github.com/lambdaclass/cairo-vm/pull/1901) -* chore: update cairo-lang dependencies to 2.10.0-rc.0 +#### [2.0.0-rc2] - 2024-12-12 * fix: Change wildcard getrandom dependency. diff --git a/Cargo.lock b/Cargo.lock index 5f956ff02e..a97304a19d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -913,7 +913,7 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "2.0.0-rc2" +version = "2.0.0-rc3" dependencies = [ "anyhow", "arbitrary", @@ -958,7 +958,7 @@ dependencies = [ [[package]] name = "cairo-vm-cli" -version = "2.0.0-rc2" +version = "2.0.0-rc3" dependencies = [ "assert_matches", "bincode", @@ -973,7 +973,7 @@ dependencies = [ [[package]] name = "cairo-vm-tracer" -version = "2.0.0-rc2" +version = "2.0.0-rc3" dependencies = [ "axum", "cairo-vm", @@ -992,7 +992,7 @@ dependencies = [ [[package]] name = "cairo1-run" -version = "2.0.0-rc2" +version = "2.0.0-rc3" dependencies = [ "assert_matches", "bincode", @@ -1662,7 +1662,7 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hint_accountant" -version = "2.0.0-rc2" +version = "2.0.0-rc3" dependencies = [ "cairo-vm", "serde", @@ -1743,7 +1743,7 @@ dependencies = [ [[package]] name = "hyper_threading" -version = "2.0.0-rc2" +version = "2.0.0-rc3" dependencies = [ "cairo-vm", "rayon", @@ -3605,7 +3605,7 @@ dependencies = [ [[package]] name = "wasm-demo" -version = "2.0.0-rc2" +version = "2.0.0-rc3" dependencies = [ "cairo-vm", "console_error_panic_hook", diff --git a/Cargo.toml b/Cargo.toml index 51e34e4172..2a9121eea1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ exclude = ["ensure-no_std"] resolver = "2" [workspace.package] -version = "2.0.0-rc2" +version = "2.0.0-rc3" edition = "2021" license = "Apache-2.0" repository = "https://github.com/lambdaclass/cairo-vm/" @@ -24,8 +24,8 @@ readme = "README.md" keywords = ["starknet", "cairo", "vm", "wasm", "no_std"] [workspace.dependencies] -cairo-vm = { path = "./vm", version = "2.0.0-rc2", default-features = false } -cairo-vm-tracer = { path = "./cairo-vm-tracer", version = "2.0.0-rc2", default-features = false } +cairo-vm = { path = "./vm", version = "2.0.0-rc3", default-features = false } +cairo-vm-tracer = { path = "./cairo-vm-tracer", version = "2.0.0-rc3", default-features = false } mimalloc = { version = "0.1.37", default-features = false } num-bigint = { version = "0.4", default-features = false, features = [ "serde", From 404d76311223c3dfe4ba26cbd4077d6a4848cda0 Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Fri, 27 Dec 2024 19:08:54 +0000 Subject: [PATCH 31/34] Fix entrypoint offset in test (#1904) * fix test * fix test * reviews * fix changed entrypoint offset on test * try fix * try fix --- vm/src/tests/cairo_1_run_from_entrypoint_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/tests/cairo_1_run_from_entrypoint_tests.rs b/vm/src/tests/cairo_1_run_from_entrypoint_tests.rs index 4ed670c679..aa1807d26c 100644 --- a/vm/src/tests/cairo_1_run_from_entrypoint_tests.rs +++ b/vm/src/tests/cairo_1_run_from_entrypoint_tests.rs @@ -39,7 +39,7 @@ fn test_uint256_div_mod_hint() { run_cairo_1_entrypoint( program_data.as_slice(), - 208, + 219, &[36_usize.into(), 2_usize.into()], &[Felt252::from(18_usize)], ); From 052e7cef977b336305c869fccbf24e1794b116ff Mon Sep 17 00:00:00 2001 From: Geoffrey Mureithi Date: Thu, 2 Jan 2025 23:17:06 +0300 Subject: [PATCH 32/34] feat: implement kzg data availability hints (#1887) * feat: kzg data availability hints Context: port of the Starknet OS to Rust. We need an implementation of the hints used by the Starknet OS in KZG commitments for data availability. This hint relies on private primitives in cairo-vm and must be implemented in this repository. * add: PR to CHANGELOG * fix: remove unnecessary clones * lint: cargo fmt --- .github/workflows/rust.yml | 2 +- CHANGELOG.md | 2 + Makefile | 9 +- .../cairo-0-kzg-da-hints/reduced_mul.cairo | 29 +++++ vm/Cargo.toml | 1 + .../builtin_hint_processor_definition.rs | 8 ++ .../builtin_hint_processor/kzg_da/mod.rs | 108 ++++++++++++++++++ .../builtin_hint_processor/mod.rs | 4 + vm/src/lib.rs | 1 + vm/src/tests/cairo_run_test.rs | 9 ++ 10 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 cairo_programs/cairo-0-kzg-da-hints/reduced_mul.cairo create mode 100644 vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b58b6d84d8..6a76308239 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -323,7 +323,7 @@ jobs: strategy: fail-fast: false matrix: - special_features: ["", "extensive_hints", "mod_builtin", "cairo-0-secp-hints"] + special_features: ["", "extensive_hints", "mod_builtin", "cairo-0-secp-hints", "cairo-0-data-availability-hints"] target: [ test#1, test#2, test#3, test#4, test-no_std#1, test-no_std#2, test-no_std#3, test-no_std#4, test-wasm ] name: Run tests runs-on: ubuntu-22.04 diff --git a/CHANGELOG.md b/CHANGELOG.md index dcc5f7e6ec..fb3f2646d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* feat: implement `kzg` data availability hints [#1887](https://github.com/lambdaclass/cairo-vm/pull/1887) + #### [2.0.0-rc3] - 2024-12-26 * chore: update cairo-lang dependencies to 2.10.0-rc.0 #[1901](https://github.com/lambdaclass/cairo-vm/pull/1901) diff --git a/Makefile b/Makefile index 7468bd0240..9b60105ab3 100644 --- a/Makefile +++ b/Makefile @@ -94,6 +94,10 @@ SECP_CAIRO0_HINTS_DIR=cairo_programs/cairo-0-secp-hints-feature SECP_CAIRO0_HINTS_FILES:=$(wildcard $(SECP_CAIRO0_HINTS_DIR)/*.cairo) COMPILED_SECP_CAIRO0_HINTS:=$(patsubst $(SECP_CAIRO0_HINTS_DIR)/%.cairo, $(SECP_CAIRO0_HINTS_DIR)/%.json, $(SECP_CAIRO0_HINTS_FILES)) +KZG_DA_CAIRO0_HINTS_DIR=cairo_programs/cairo-0-kzg-da-hints +KZG_DA_CAIRO0_HINTS_FILES:=$(wildcard $(KZG_DA_CAIRO0_HINTS_DIR)/*.cairo) +COMPILED_KZG_DA_CAIRO0_HINTS:=$(patsubst $(KZG_DA_CAIRO0_HINTS_DIR)/%.cairo, $(KZG_DA_CAIRO0_HINTS_DIR)/%.json, $(KZG_DA_CAIRO0_HINTS_FILES)) + PRINT_TEST_DIR=cairo_programs/print_feature PRINT_TEST_FILES:=$(wildcard $(PRINT_TEST_DIR)/*.cairo) COMPILED_PRINT_TESTS:=$(patsubst $(PRINT_TEST_DIR)/%.cairo, $(PRINT_TEST_DIR)/%.json, $(PRINT_TEST_FILES)) @@ -243,7 +247,7 @@ run: check: cargo check -cairo_test_programs: $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) $(COMPILED_PRINT_TESTS) $(COMPILED_MOD_BUILTIN_TESTS) $(COMPILED_SECP_CAIRO0_HINTS) +cairo_test_programs: $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) $(COMPILED_PRINT_TESTS) $(COMPILED_MOD_BUILTIN_TESTS) $(COMPILED_SECP_CAIRO0_HINTS) $(COMPILED_KZG_DA_CAIRO0_HINTS) cairo_proof_programs: $(COMPILED_PROOF_TESTS) $(COMPILED_MOD_BUILTIN_PROOF_TESTS) cairo_bench_programs: $(COMPILED_BENCHES) cairo_1_test_contracts: $(CAIRO_1_COMPILED_CASM_CONTRACTS) @@ -268,7 +272,7 @@ test-wasm: cairo_proof_programs cairo_test_programs # NOTE: release mode is needed to avoid "too many locals" error wasm-pack test --release --node vm --no-default-features test-extensive_hints: cairo_proof_programs cairo_test_programs - $(TEST_COMMAND) --workspace --features "test_utils, cairo-1-hints, cairo-0-secp-hints, extensive_hints" + $(TEST_COMMAND) --workspace --features "test_utils, cairo-1-hints, cairo-0-secp-hints, cairo-0-data-availability-hints, extensive_hints" check-fmt: cargo fmt --all -- --check @@ -349,6 +353,7 @@ clean: rm -f $(BENCH_DIR)/*.json rm -f $(BAD_TEST_DIR)/*.json rm -f $(SECP_CAIRO0_HINTS_DIR)/*.json + rm -f $(KZG_DA_CAIRO0_HINTS_DIR)/*.json rm -f $(PRINT_TEST_DIR)/*.json rm -f $(CAIRO_1_CONTRACTS_TEST_DIR)/*.sierra rm -f $(CAIRO_1_CONTRACTS_TEST_DIR)/*.casm diff --git a/cairo_programs/cairo-0-kzg-da-hints/reduced_mul.cairo b/cairo_programs/cairo-0-kzg-da-hints/reduced_mul.cairo new file mode 100644 index 0000000000..8f54d7d0cb --- /dev/null +++ b/cairo_programs/cairo-0-kzg-da-hints/reduced_mul.cairo @@ -0,0 +1,29 @@ +%builtins range_check + +from starkware.starknet.core.os.data_availability.bls_field import reduced_mul, BigInt3 + +func main{range_check_ptr: felt}() { + let x = BigInt3(0, 0, 0); + let y = BigInt3(1, 1, 1); + + let res = reduced_mul(x, y); + + assert res = BigInt3(0, 0, 0); + + let x = BigInt3(100, 99, 98); + let y = BigInt3(10, 9, 8); + + let res = reduced_mul(x, y); + + assert res = BigInt3( + 49091481911800146991175221, 43711329369885800715738617, 405132241597509509195407 + ); + + let x = BigInt3(47503316700827173496989353, 17218105161352860131668522, 527908748911931938599018); + let y = BigInt3(50964737623371959432443726, 60451660835701602854498663, 5043009036652075489876599); + + let res = reduced_mul(x, y); + assert res = BigInt3(43476011663489831917914902, 15057238271740518603165849, 1923992965848504555868221); + + return (); +} diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 3437a30034..a01a0ce2c0 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -30,6 +30,7 @@ cairo-1-hints = [ tracer = [] mod_builtin = [] cairo-0-secp-hints = [] +cairo-0-data-availability-hints = [] # Note that these features are not retro-compatible with the cairo Python VM. test_utils = ["std", "dep:arbitrary", "starknet-types-core/arbitrary", "starknet-types-core/std"] # This feature will reference every test-oriented feature diff --git a/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index 15c8318b15..f5ae7a96c4 100644 --- a/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -966,6 +966,14 @@ impl HintProcessorLogic for BuiltinHintProcessor { &hint_data.ap_tracking, constants, ), + #[cfg(feature = "cairo-0-data-availability-hints")] + super::kzg_da::WRITE_DIVMOD_SEGMENT => super::kzg_da::write_div_mod_segment( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), code => Err(HintError::UnknownHint(code.to_string().into_boxed_str())), } diff --git a/vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs b/vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs new file mode 100644 index 0000000000..8da7274056 --- /dev/null +++ b/vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs @@ -0,0 +1,108 @@ +use core::str::FromStr; + +use super::{ + hint_utils::get_relocatable_from_var_name, + secp::{bigint_utils::BigInt3, secp_utils::SECP_P}, +}; +use crate::{ + hint_processor::hint_processor_definition::HintReference, + serde::deserialize_program::ApTracking, + types::relocatable::MaybeRelocatable, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, + Felt252, +}; +use crate::{ + stdlib::{collections::HashMap, ops::Deref, prelude::*}, + types::exec_scope::ExecutionScopes, +}; +use lazy_static::lazy_static; +use num_bigint::BigInt; +use num_integer::Integer; +use num_traits::FromPrimitive; +use num_traits::Zero; + +lazy_static! { + static ref BLS_BASE: BigInt = BigInt::from_u64(2).unwrap().pow(86); + static ref BLS_PRIME: BigInt = BigInt::from_str( + "52435875175126190479447740508185965837690552500527637822603658699938581184513" + ) + .unwrap(); +} +pub const WRITE_DIVMOD_SEGMENT: &str = r#"from starkware.starknet.core.os.data_availability.bls_utils import BLS_PRIME, pack, split + +a = pack(ids.a, PRIME) +b = pack(ids.b, PRIME) + +q, r = divmod(a * b, BLS_PRIME) + +# By the assumption: |a|, |b| < 2**104 * ((2**86) ** 2 + 2**86 + 1) < 2**276.001. +# Therefore |q| <= |ab| / BLS_PRIME < 2**299. +# Hence the absolute value of the high limb of split(q) < 2**127. +segments.write_arg(ids.q.address_, split(q)) +segments.write_arg(ids.res.address_, split(r))"#; + +pub fn write_div_mod_segment( + vm: &mut VirtualMachine, + _exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + let a = bls_pack( + &BigInt3::from_var_name("a", vm, ids_data, ap_tracking)?, + &SECP_P, + ); + let b = bls_pack( + &BigInt3::from_var_name("b", vm, ids_data, ap_tracking)?, + &SECP_P, + ); + let (q, r) = (a * b).div_mod_floor(&BLS_PRIME); + let q_reloc = get_relocatable_from_var_name("q", vm, ids_data, ap_tracking)?; + let res_reloc = get_relocatable_from_var_name("res", vm, ids_data, ap_tracking)?; + + let q_arg: Vec = bls_split(q) + .into_iter() + .map(|ref n| Felt252::from(n).into()) + .collect::>(); + let res_arg: Vec = bls_split(r) + .into_iter() + .map(|ref n| Felt252::from(n).into()) + .collect::>(); + vm.write_arg(q_reloc, &q_arg).map_err(HintError::Memory)?; + vm.write_arg(res_reloc, &res_arg) + .map_err(HintError::Memory)?; + Ok(()) +} + +fn bls_split(mut num: BigInt) -> Vec { + use num_traits::Signed; + let mut a = Vec::new(); + for _ in 0..2 { + let residue = &num % BLS_BASE.deref(); + num /= BLS_BASE.deref(); + a.push(residue); + } + assert!(num.abs() < BigInt::from_u128(1 << 127).unwrap()); + a.push(num); + a +} + +fn as_int(value: BigInt, prime: &BigInt) -> BigInt { + let half_prime = prime / 2u32; + if value > half_prime { + value - prime + } else { + value + } +} + +fn bls_pack(z: &BigInt3, prime: &BigInt) -> BigInt { + let limbs = &z.limbs; + limbs + .iter() + .enumerate() + .fold(BigInt::zero(), |acc, (i, limb)| { + let limb_as_int = as_int(limb.to_bigint(), prime); + acc + limb_as_int * &BLS_BASE.pow(i as u32) + }) +} diff --git a/vm/src/hint_processor/builtin_hint_processor/mod.rs b/vm/src/hint_processor/builtin_hint_processor/mod.rs index dd647ca944..497c556913 100644 --- a/vm/src/hint_processor/builtin_hint_processor/mod.rs +++ b/vm/src/hint_processor/builtin_hint_processor/mod.rs @@ -38,3 +38,7 @@ pub mod uint384_extension; pub mod uint_utils; pub mod usort; pub mod vrf; + +#[cfg(feature = "cairo-0-data-availability-hints")] +#[cfg_attr(docsrs, doc(cfg(feature = "cairo-0-data-availability-hints")))] +pub mod kzg_da; diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 90545d0f47..22798e3f97 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -9,6 +9,7 @@ //! - implementations of [`arbitrary::Arbitrary`](https://docs.rs/arbitrary/latest/arbitrary/) for some structs. //! - `cairo-1-hints`: Enable hints that were introduced in Cairo 1. Not enabled by default. //! - `cairo-0-secp-hints`: Enable secp hints that were introduced in Cairo 0. Not enabled by default. +//! - `cairo-0-data-availability-hints`: Enable data availability hints that were introduced in Cairo 0. Not enabled by default. #![cfg_attr(docsrs, feature(doc_cfg))] #![deny(warnings)] diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index f33ed945de..d847852929 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -1308,3 +1308,12 @@ fn cairo_run_secp_cairo0_ec_mul_by_uint256() { ); run_program_simple(program_data.as_slice()); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +#[cfg(feature = "cairo-0-data-availability-hints")] +fn cairo_run_data_availability_reduced_mul() { + let program_data = + include_bytes!("../../../cairo_programs/cairo-0-kzg-da-hints/reduced_mul.json"); + run_program_simple(program_data.as_slice()); +} From 87c10b3ac6422486b5bc6b117eb7f67ccd1e77ee Mon Sep 17 00:00:00 2001 From: Franco Giachetta Date: Fri, 3 Jan 2025 20:58:19 +0000 Subject: [PATCH 33/34] Add support for subtractions contenting references as right hand side operands (#1898) * take into account the sign of the reference * resolve conflicts * fix issue * add test with negated outer reference * update changelog * test passing * explain unreachable * format * fix test * fix test and changelog * revert changes in custom_hint/custom_hint.rs * remove unwanted files * Update CHANGELOG.md Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> * Update vm/src/types/errors/program_errors.rs typo Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> --------- Co-authored-by: Gabriel Bosio <38794644+gabrielbosio@users.noreply.github.com> --- CHANGELOG.md | 2 + .../builtin_hint_processor/hint_utils.rs | 2 +- .../builtin_hint_processor/math_utils.rs | 70 ++++++++++++--- .../hint_processor_definition.rs | 16 ++-- vm/src/hint_processor/hint_processor_utils.rs | 35 ++++---- vm/src/serde/deserialize_program.rs | 10 +-- vm/src/serde/deserialize_utils.rs | 86 +++++++++++++------ vm/src/types/errors/program_errors.rs | 2 + vm/src/types/program.rs | 4 +- vm/src/vm/errors/vm_exception.rs | 2 +- 10 files changed, 162 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb3f2646d7..d0cd50c54b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ #### [2.0.0-rc2] - 2024-12-12 +* feat: Add support for subtractions containing references as right hand side operands [#1898](https://github.com/lambdaclass/cairo-vm/pull/1898) + * fix: Change wildcard getrandom dependency. * Update starknet-crypto to 0.7.3, removing the old FieldElement completly in favour of the new Felt (that is Copy). diff --git a/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs b/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs index 74caa13473..e104cb7e86 100644 --- a/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs @@ -149,7 +149,7 @@ mod tests { fn get_ptr_from_var_name_immediate_value() { let mut vm = vm!(); vm.segments = segments![((1, 0), (0, 0))]; - let mut hint_ref = HintReference::new(0, 0, true, false); + let mut hint_ref = HintReference::new(0, 0, true, false, true); hint_ref.offset2 = OffsetValue::Value(2); let ids_data = HashMap::from([("imm".to_string(), hint_ref)]); diff --git a/vm/src/hint_processor/builtin_hint_processor/math_utils.rs b/vm/src/hint_processor/builtin_hint_processor/math_utils.rs index e10467b6ee..eb65aed496 100644 --- a/vm/src/hint_processor/builtin_hint_processor/math_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/math_utils.rs @@ -2053,8 +2053,14 @@ mod tests { //Create ids let ids_data = HashMap::from([ ("value".to_string(), HintReference::new_simple(-4)), - ("low".to_string(), HintReference::new(-3, 0, true, true)), - ("high".to_string(), HintReference::new(-3, 1, true, true)), + ( + "low".to_string(), + HintReference::new(-3, 0, true, true, true), + ), + ( + "high".to_string(), + HintReference::new(-3, 1, true, true, true), + ), ]); //Execute the hint assert_matches!( @@ -2131,8 +2137,14 @@ mod tests { //Create ids_data & hint_data let ids_data = HashMap::from([ ("value".to_string(), HintReference::new_simple(-4)), - ("low".to_string(), HintReference::new(-3, 0, true, true)), - ("high".to_string(), HintReference::new(-3, 1, true, true)), + ( + "low".to_string(), + HintReference::new(-3, 0, true, true, true), + ), + ( + "high".to_string(), + HintReference::new(-3, 1, true, true, true), + ), ]); //Execute the hint @@ -2175,8 +2187,14 @@ mod tests { //Create ids_data & hint_data let ids_data = HashMap::from([ ("value".to_string(), HintReference::new_simple(-4)), - ("low".to_string(), HintReference::new(-3, 0, true, true)), - ("high".to_string(), HintReference::new(-3, 1, true, true)), + ( + "low".to_string(), + HintReference::new(-3, 0, true, true, true), + ), + ( + "high".to_string(), + HintReference::new(-3, 1, true, true, true), + ), ]); //Execute the hint assert_matches!( @@ -2213,8 +2231,14 @@ mod tests { //Create ids_data & hint_data let ids_data = HashMap::from([ ("value".to_string(), HintReference::new_simple(-4)), - ("low".to_string(), HintReference::new(-3, 0, true, true)), - ("high".to_string(), HintReference::new(-3, 1, true, true)), + ( + "low".to_string(), + HintReference::new(-3, 0, true, true, true), + ), + ( + "high".to_string(), + HintReference::new(-3, 1, true, true, true), + ), ]); //Execute the hint assert_matches!( @@ -2251,8 +2275,14 @@ mod tests { //Create ids let ids_data = HashMap::from([ ("value".to_string(), HintReference::new_simple(-4)), - ("low".to_string(), HintReference::new(-3, 0, true, true)), - ("high".to_string(), HintReference::new(-3, 1, true, true)), + ( + "low".to_string(), + HintReference::new(-3, 0, true, true, true), + ), + ( + "high".to_string(), + HintReference::new(-3, 1, true, true, true), + ), ]); //Execute the hint assert_matches!( @@ -2277,8 +2307,14 @@ mod tests { //Create ids let ids_data = HashMap::from([ ("value".to_string(), HintReference::new_simple(-4)), - ("low".to_string(), HintReference::new(-3, 0, true, true)), - ("high".to_string(), HintReference::new(-3, 1, true, true)), + ( + "low".to_string(), + HintReference::new(-3, 0, true, true, true), + ), + ( + "high".to_string(), + HintReference::new(-3, 1, true, true, true), + ), ]); //Execute the hint assert_matches!( @@ -2315,8 +2351,14 @@ mod tests { //Create ids let ids_data = HashMap::from([ ("value".to_string(), HintReference::new_simple(-4)), - ("low".to_string(), HintReference::new(-3, 0, true, true)), - ("high".to_string(), HintReference::new(-3, 1, true, true)), + ( + "low".to_string(), + HintReference::new(-3, 0, true, true, true), + ), + ( + "high".to_string(), + HintReference::new(-3, 1, true, true, true), + ), ]); //Execute the hint assert_matches!( diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index 496e8b1428..d4c871903a 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -112,7 +112,7 @@ pub struct HintReference { impl HintReference { pub fn new_simple(offset1: i32) -> Self { HintReference { - offset1: OffsetValue::Reference(Register::FP, offset1, false), + offset1: OffsetValue::Reference(Register::FP, offset1, false, true), offset2: OffsetValue::Value(0), ap_tracking_data: None, outer_dereference: true, @@ -121,9 +121,15 @@ impl HintReference { } } - pub fn new(offset1: i32, offset2: i32, inner_dereference: bool, dereference: bool) -> Self { + pub fn new( + offset1: i32, + offset2: i32, + inner_dereference: bool, + dereference: bool, + is_positive: bool, + ) -> Self { HintReference { - offset1: OffsetValue::Reference(Register::FP, offset1, inner_dereference), + offset1: OffsetValue::Reference(Register::FP, offset1, inner_dereference, is_positive), offset2: OffsetValue::Value(offset2), ap_tracking_data: None, outer_dereference: dereference, @@ -145,8 +151,8 @@ impl From for HintReference { &reference.value_address.offset1, &reference.value_address.offset2, ) { - (OffsetValue::Reference(Register::AP, _, _), _) - | (_, OffsetValue::Reference(Register::AP, _, _)) => { + (OffsetValue::Reference(Register::AP, _, _, _), _) + | (_, OffsetValue::Reference(Register::AP, _, _, _)) => { Some(reference.ap_tracking_data.clone()) } _ => None, diff --git a/vm/src/hint_processor/hint_processor_utils.rs b/vm/src/hint_processor/hint_processor_utils.rs index 8a0a3e9e58..3d442fbf7f 100644 --- a/vm/src/hint_processor/hint_processor_utils.rs +++ b/vm/src/hint_processor/hint_processor_utils.rs @@ -70,7 +70,12 @@ pub fn get_maybe_relocatable_from_reference( &hint_reference.ap_tracking_data, ap_tracking, )?; - let mut val = offset1.add(&offset2).ok()?; + let mut val = match hint_reference.offset2 { + OffsetValue::Reference(_, _, _, true) + | OffsetValue::Immediate(_) + | OffsetValue::Value(_) => offset1.add(&offset2).ok()?, + OffsetValue::Reference(_, _, _, false) => offset1.sub(&offset2).ok()?, + }; if hint_reference.inner_dereference && hint_reference.outer_dereference { val = vm.get_maybe(&val)?; } @@ -139,7 +144,7 @@ fn get_offset_value( match offset_value { OffsetValue::Immediate(f) => Some(f.into()), OffsetValue::Value(v) => Some(Felt252::from(*v).into()), - OffsetValue::Reference(register, offset, deref) => { + OffsetValue::Reference(register, offset, deref, _) => { let addr = (if matches!(register, Register::FP) { vm.get_fp() } else { @@ -176,7 +181,7 @@ mod tests { // Reference: cast(2, felt) let mut vm = vm!(); vm.segments = segments![((1, 0), 0)]; - let mut hint_ref = HintReference::new(0, 0, false, false); + let mut hint_ref = HintReference::new(0, 0, false, false, true); hint_ref.offset1 = OffsetValue::Immediate(Felt252::from(2)); assert_eq!( @@ -191,8 +196,8 @@ mod tests { fn get_offset_value_reference_valid() { let mut vm = vm!(); vm.segments = segments![((1, 0), 0)]; - let mut hint_ref = HintReference::new(0, 0, false, true); - hint_ref.offset1 = OffsetValue::Reference(Register::FP, 2_i32, false); + let mut hint_ref = HintReference::new(0, 0, false, true, true); + hint_ref.offset1 = OffsetValue::Reference(Register::FP, 2_i32, false, true); assert_matches!( get_offset_value(&vm, &hint_ref.offset1, &hint_ref.ap_tracking_data, &ApTracking::new()), @@ -205,8 +210,8 @@ mod tests { fn get_offset_value_invalid() { let mut vm = vm!(); vm.segments = segments![((1, 0), 0)]; - let mut hint_ref = HintReference::new(0, 0, false, true); - hint_ref.offset1 = OffsetValue::Reference(Register::FP, -2_i32, false); + let mut hint_ref = HintReference::new(0, 0, false, true, true); + hint_ref.offset1 = OffsetValue::Reference(Register::FP, -2_i32, false, true); assert_matches!( get_offset_value( @@ -228,7 +233,7 @@ mod tests { assert_matches!( get_ptr_from_reference( &vm, - &HintReference::new(0, 0, false, false), + &HintReference::new(0, 0, false, false, true), &ApTracking::new() ), Ok(x) if x == relocatable!(1, 0) @@ -244,7 +249,7 @@ mod tests { assert_matches!( get_ptr_from_reference( &vm, - &HintReference::new(0, 0, false, true), + &HintReference::new(0, 0, false, true, true), &ApTracking::new() ), Ok(x) if x == relocatable!(3, 0) @@ -256,7 +261,7 @@ mod tests { fn get_ptr_from_reference_with_dereference_and_imm() { let mut vm = vm!(); vm.segments = segments![((1, 0), (4, 0))]; - let mut hint_ref = HintReference::new(0, 0, true, false); + let mut hint_ref = HintReference::new(0, 0, true, false, true); hint_ref.offset2 = OffsetValue::Value(2); assert_matches!( @@ -270,7 +275,7 @@ mod tests { fn compute_addr_from_reference_no_regiter_in_reference() { let mut vm = vm!(); vm.segments = segments![((1, 0), (4, 0))]; - let mut hint_reference = HintReference::new(0, 0, false, false); + let mut hint_reference = HintReference::new(0, 0, false, false, true); hint_reference.offset1 = OffsetValue::Immediate(Felt252::from(2_i32)); assert!(compute_addr_from_reference(&hint_reference, &vm, &ApTracking::new()).is_none()); @@ -282,8 +287,8 @@ mod tests { let mut vm = vm!(); vm.segments = segments![((1, 0), 4)]; // vm.run_context.fp = -1; - let mut hint_reference = HintReference::new(0, 0, false, false); - hint_reference.offset1 = OffsetValue::Reference(Register::FP, -1, true); + let mut hint_reference = HintReference::new(0, 0, false, false, true); + hint_reference.offset1 = OffsetValue::Reference(Register::FP, -1, true, true); assert_matches!( compute_addr_from_reference(&hint_reference, &vm, &ApTracking::new()), @@ -356,7 +361,7 @@ mod tests { ((0, 5), 3) // [[[fp + 2] + 2]] -> [(0, 5)] -> 3 ]; let hint_ref = HintReference { - offset1: OffsetValue::Reference(Register::FP, 2, true), + offset1: OffsetValue::Reference(Register::FP, 2, true, true), offset2: OffsetValue::Value(2), outer_dereference: true, inner_dereference: true, @@ -381,7 +386,7 @@ mod tests { ]; // [fp + 4] + (-5) = 8 - 5 = 3 let hint_ref = HintReference { - offset1: OffsetValue::Reference(Register::FP, 4, true), + offset1: OffsetValue::Reference(Register::FP, 4, true, true), offset2: OffsetValue::Immediate(Felt252::from(-5)), outer_dereference: false, inner_dereference: false, diff --git a/vm/src/serde/deserialize_program.rs b/vm/src/serde/deserialize_program.rs index 82771f7552..8f0e9a0dee 100644 --- a/vm/src/serde/deserialize_program.rs +++ b/vm/src/serde/deserialize_program.rs @@ -275,7 +275,7 @@ pub struct Reference { pub enum OffsetValue { Immediate(Felt252), Value(i32), - Reference(Register, i32, bool), + Reference(Register, i32, bool, bool), } #[cfg_attr(feature = "test_utils", derive(Arbitrary))] @@ -714,7 +714,7 @@ mod tests { }, pc: Some(0), value_address: ValueAddress { - offset1: OffsetValue::Reference(Register::FP, -4, false), + offset1: OffsetValue::Reference(Register::FP, -4, false, true), offset2: OffsetValue::Value(0), outer_dereference: true, inner_dereference: false, @@ -728,7 +728,7 @@ mod tests { }, pc: Some(0), value_address: ValueAddress { - offset1: OffsetValue::Reference(Register::FP, -3, false), + offset1: OffsetValue::Reference(Register::FP, -3, false, true), offset2: OffsetValue::Value(0), outer_dereference: true, inner_dereference: false, @@ -742,7 +742,7 @@ mod tests { }, pc: Some(0), value_address: ValueAddress { - offset1: OffsetValue::Reference(Register::FP, -3, true), + offset1: OffsetValue::Reference(Register::FP, -3, true, true), offset2: OffsetValue::Immediate(Felt252::from(2)), outer_dereference: false, inner_dereference: false, @@ -756,7 +756,7 @@ mod tests { }, pc: Some(0), value_address: ValueAddress { - offset1: OffsetValue::Reference(Register::FP, 0, false), + offset1: OffsetValue::Reference(Register::FP, 0, false, true), offset2: OffsetValue::Value(0), outer_dereference: true, inner_dereference: false, diff --git a/vm/src/serde/deserialize_utils.rs b/vm/src/serde/deserialize_utils.rs index 8179605c52..7b4c7bb20e 100644 --- a/vm/src/serde/deserialize_utils.rs +++ b/vm/src/serde/deserialize_utils.rs @@ -125,7 +125,17 @@ fn inner_dereference(input: &str) -> IResult<&str, OffsetValue> { if input.is_empty() { return Ok(("", OffsetValue::Value(0))); } - let (input, _sign) = opt(alt((tag(" + "), tag(" - "))))(input)?; + let (input, sign) = opt(alt((tag(" + "), tag(" - "))))(input)?; + + let is_positive = match sign { + Some(s) => match s.trim() { + "+" => true, + "-" => false, + // can't happen since the alt parser only takes "+" or "-" + _ => unreachable!(), + }, + None => true, + }; map_res( delimited(tag("["), take_until("]"), tag("]")), @@ -135,7 +145,7 @@ fn inner_dereference(input: &str) -> IResult<&str, OffsetValue> { let (_, (register, offset)) = res; let offset_value = match register { None => OffsetValue::Value(offset), - Some(reg) => OffsetValue::Reference(reg, offset, true), + Some(reg) => OffsetValue::Reference(reg, offset, true, is_positive), }; (rem_input, offset_value) }) @@ -145,7 +155,7 @@ fn no_inner_dereference(input: &str) -> IResult<&str, OffsetValue> { let (rem_input, (register, offset)) = register_and_offset(input)?; let offset_value = match register { None => OffsetValue::Value(offset), - Some(reg) => OffsetValue::Reference(reg, offset, false), + Some(reg) => OffsetValue::Reference(reg, offset, false, true), }; Ok((rem_input, offset_value)) } @@ -177,13 +187,17 @@ pub(crate) fn parse_value(input: &str) -> IResult<&str, ValueAddress> { let offset1 = match fst_offset { OffsetValue::Immediate(imm) => OffsetValue::Immediate(imm), OffsetValue::Value(val) => OffsetValue::Immediate(Felt252::from(val)), - OffsetValue::Reference(reg, val, refe) => OffsetValue::Reference(reg, val, refe), + OffsetValue::Reference(reg, val, refe, is_positive) => { + OffsetValue::Reference(reg, val, refe, is_positive) + } }; let offset2 = match snd_offset { OffsetValue::Immediate(imm) => OffsetValue::Immediate(imm), OffsetValue::Value(val) => OffsetValue::Immediate(Felt252::from(val)), - OffsetValue::Reference(reg, val, refe) => OffsetValue::Reference(reg, val, refe), + OffsetValue::Reference(reg, val, refe, is_positive) => { + OffsetValue::Reference(reg, val, refe, is_positive) + } }; (offset1, offset2) @@ -368,7 +382,10 @@ mod tests { assert_eq!( parsed, - Ok((" + 2", OffsetValue::Reference(Register::FP, -1_i32, true))) + Ok(( + " + 2", + OffsetValue::Reference(Register::FP, -1_i32, true, true) + )) ); } @@ -380,7 +397,7 @@ mod tests { assert_eq!( parsed, - Ok(("", OffsetValue::Reference(Register::AP, 3_i32, false))) + Ok(("", OffsetValue::Reference(Register::AP, 3_i32, false, true))) ); } @@ -396,7 +413,7 @@ mod tests { "", ValueAddress { offset2: OffsetValue::Value(2), - offset1: OffsetValue::Reference(Register::FP, -1_i32, true), + offset1: OffsetValue::Reference(Register::FP, -1_i32, true, true), outer_dereference: true, inner_dereference: false, value_type: "felt".to_string(), @@ -405,6 +422,27 @@ mod tests { ); } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn parse_value_with_neg_inner_dereference_test() { + let value = "cast(17 - [fp], felt)"; + let parsed = parse_value(value).unwrap(); + + assert_eq!( + parsed, + ( + "", + ValueAddress { + offset1: OffsetValue::Immediate(Felt252::from(17)), + offset2: OffsetValue::Reference(Register::FP, 0_i32, true, false), + outer_dereference: false, + inner_dereference: false, + value_type: "felt".to_string() + } + ) + ) + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn parse_value_with_no_inner_dereference_test() { @@ -416,7 +454,7 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 2_i32, false), + offset1: OffsetValue::Reference(Register::AP, 2_i32, false, true), offset2: OffsetValue::Value(0), outer_dereference: false, inner_dereference: false, @@ -457,7 +495,7 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 0_i32, false), + offset1: OffsetValue::Reference(Register::AP, 0_i32, false, true), offset2: OffsetValue::Value(-1), outer_dereference: true, inner_dereference: false, @@ -478,7 +516,7 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 0_i32, true), + offset1: OffsetValue::Reference(Register::AP, 0_i32, true, true), offset2: OffsetValue::Value(1), outer_dereference: true, inner_dereference: false, @@ -499,7 +537,7 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 0_i32, true), + offset1: OffsetValue::Reference(Register::AP, 0_i32, true, true), offset2: OffsetValue::Immediate(Felt252::ONE), outer_dereference: true, inner_dereference: false, @@ -520,7 +558,7 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 1_i32, true), + offset1: OffsetValue::Reference(Register::AP, 1_i32, true, true), offset2: OffsetValue::Value(1), outer_dereference: true, inner_dereference: false, @@ -541,8 +579,8 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 0_i32, true), - offset2: OffsetValue::Reference(Register::FP, 1_i32, true), + offset1: OffsetValue::Reference(Register::AP, 0_i32, true, true), + offset2: OffsetValue::Reference(Register::FP, 1_i32, true, true), outer_dereference: true, inner_dereference: false, value_type: "__main__.felt".to_string(), @@ -562,8 +600,8 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 1_i32, true), - offset2: OffsetValue::Reference(Register::FP, 1_i32, true), + offset1: OffsetValue::Reference(Register::AP, 1_i32, true, true), + offset2: OffsetValue::Reference(Register::FP, 1_i32, true, true), outer_dereference: true, inner_dereference: false, value_type: "__main__.felt".to_string(), @@ -604,7 +642,7 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 0_i32, true), + offset1: OffsetValue::Reference(Register::AP, 0_i32, true, true), offset2: OffsetValue::Value(1), outer_dereference: true, inner_dereference: false, @@ -625,7 +663,7 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 0_i32, true), + offset1: OffsetValue::Reference(Register::AP, 0_i32, true, true), offset2: OffsetValue::Value(1), outer_dereference: true, inner_dereference: false, @@ -646,8 +684,8 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 0_i32, true), - offset2: OffsetValue::Reference(Register::AP, 0_i32, true), + offset1: OffsetValue::Reference(Register::AP, 0_i32, true, true), + offset2: OffsetValue::Reference(Register::AP, 0_i32, true, true), outer_dereference: true, inner_dereference: false, value_type: "felt".to_string(), @@ -667,7 +705,7 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::FP, -3_i32, true), + offset1: OffsetValue::Reference(Register::FP, -3_i32, true, true), offset2: OffsetValue::Value(5), outer_dereference: true, inner_dereference: true, @@ -688,8 +726,8 @@ mod tests { Ok(( "", ValueAddress { - offset1: OffsetValue::Reference(Register::AP, 1_i32, true), - offset2: OffsetValue::Reference(Register::AP, 2_i32, true), + offset1: OffsetValue::Reference(Register::AP, 1_i32, true, true), + offset2: OffsetValue::Reference(Register::AP, 2_i32, true, true), outer_dereference: true, inner_dereference: false, value_type: "felt".to_string(), diff --git a/vm/src/types/errors/program_errors.rs b/vm/src/types/errors/program_errors.rs index e4a7c96d90..77f62585e0 100644 --- a/vm/src/types/errors/program_errors.rs +++ b/vm/src/types/errors/program_errors.rs @@ -9,6 +9,8 @@ pub enum ProgramError { IO(#[from] std::io::Error), #[error(transparent)] Parse(#[from] serde_json::Error), + #[error("The \"{0}\" operation is not supported")] + OperationNotSupported(String), #[error("Entrypoint {0} not found")] EntrypointNotFound(String), #[error("Constant {0} has no value")] diff --git a/vm/src/types/program.rs b/vm/src/types/program.rs index 1c97580ee0..fcc2cb1a3e 100644 --- a/vm/src/types/program.rs +++ b/vm/src/types/program.rs @@ -344,8 +344,8 @@ impl Program { inner_dereference: r.value_address.inner_dereference, // only store `ap` tracking data if the reference is referred to it ap_tracking_data: match (&r.value_address.offset1, &r.value_address.offset2) { - (OffsetValue::Reference(Register::AP, _, _), _) - | (_, OffsetValue::Reference(Register::AP, _, _)) => { + (OffsetValue::Reference(Register::AP, _, _, _), _) + | (_, OffsetValue::Reference(Register::AP, _, _, _)) => { Some(r.ap_tracking_data.clone()) } _ => None, diff --git a/vm/src/vm/errors/vm_exception.rs b/vm/src/vm/errors/vm_exception.rs index 5a31d6669c..005160d95b 100644 --- a/vm/src/vm/errors/vm_exception.rs +++ b/vm/src/vm/errors/vm_exception.rs @@ -177,7 +177,7 @@ fn get_value_from_simple_reference( .get(ref_id)?; // Filter ap-based references match reference.offset1 { - OffsetValue::Reference(Register::AP, _, _) => None, + OffsetValue::Reference(Register::AP, _, _, _) => None, _ => { // Filer complex types (only felt/felt pointers) match reference.cairo_type { From 259487e5c12fe1fd5912ea540b075a5f4a98456a Mon Sep 17 00:00:00 2001 From: Julian Gonzalez Calderon Date: Mon, 6 Jan 2025 13:13:31 -0300 Subject: [PATCH 34/34] Consolidate VM documentation (#1866) * Add tooling section * Link to new section with doc * Copy documentation * Remove unused section * Fix typo * Clean up doc * Add instruction format section * Add more todos * Add description to some tools * Ack doc source * Add hint and builtin documentation * Remove extra todo * Fix grammar error * Update prover link * Mention Code Walkthrough * Remove TODO * Add example --- docs/README.md | 10 ++ docs/vm/README.md | 361 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 docs/vm/README.md diff --git a/docs/README.md b/docs/README.md index 5d70a46fea..c781d4d706 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,6 @@ # Documentation + +* [How does the Cairo VM work?](./vm/) * [How does the original Cairo VM work?](./python_vm/) * [Benchmarks](./benchmarks/) * [Custom Hint Processor](./hint_processor/) @@ -6,3 +8,11 @@ * [References parsing](./references_parsing/) * [Tracer](./tracer/) * [Debugging](./debugging.md) + +## Tooling + +* [cairo1-run](/cairo1-run): Execute Cairo 1 programs +* [cairo-vm-cli](/cairo-vm-cli): Execute Cairo 0 programs +* [cairo-vm-tracer](/cairo-vm-tracer) +* [fuzzer](/fuzzer) +* [hint_accountant](/hint_accountant) diff --git a/docs/vm/README.md b/docs/vm/README.md new file mode 100644 index 0000000000..f340a4b8c2 --- /dev/null +++ b/docs/vm/README.md @@ -0,0 +1,361 @@ + + +# How does the Cairo VM work? + +## High Level Overview + +The Cairo virtual machine is meant to be used in the context of STARK validity proofs. What this means is that the point of Cairo is not just to execute some code and get a result, but to *prove* to someone else that said execution was done correctly, without them having to re-execute the entire thing. The rough flow for it looks like this: + +- A user writes a Cairo program. +- The program is compiled into Cairo's VM bytecode. +- The VM executes said code and provides a *trace* of execution, i.e. a record of the state of the machine and its memory *at every step of the computation*. +- This trace is passed on to a STARK prover, which creates a cryptographic proof from it, attesting to the correct execution of the program. +- The proof is passed to a verifier, who checks that the proof is valid in a fraction of a second, without re-executing. + +The main three components of this flow are: + +- A Cairo compiler to turn a program written in the [Cairo programming language](https://www.cairo-lang.org/) into bytecode. +- A Cairo VM to then execute it and generate a trace. +- [A STARK prover and verifier](https://github.com/starkware-libs/stone-prover/tree/main) so one party can prove correct execution, while another can verify it. + +While this repo is only concerned with the second component, it's important to keep in mind the other two; especially important are the prover and verifier that this VM feeds its trace to, as a lot of its design decisions come from them. This virtual machine is designed to make proving and verifying both feasible and fast, and that makes it quite different from most other VMs you are probably used to. + +## Basic VM flow + +Our virtual machine has a very simple flow: + +- Take a compiled cairo program as input. You can check out an example program [here](https://github.com/lambdaclass/cairo-vm.go/blob/main/cairo_programs/fibonacci.cairo). +- Run the bytecode from the compiled program, doing the usual `fetch->decode->execute` loop, running until program termination. +- On every step of the execution, record the values of each register. +- Take the register values and memory at every step and write them to a file, called the `execution trace`. + +Barring some simplifications we made, this is all the Cairo VM does. The two main things that stand out as radically different are the memory model and the use of `Field Elements` to perform arithmetic. Below we go into more detail on each step, and in the process explain the ommisions we made. + +## Memory + +The Cairo virtual machine uses a Von Neumann architecture with a Non-deterministic read-only memory. What this means, roughly, is that memory is immutable after you've written to it (i.e. you can only write to it once); this is to make the STARK proving easier, but we won't go into that here. + +### Memory Segments and Relocation + +The process of memory allocation in a contiguous write-once memory region can get pretty complicated. Imagine you want to have a regular call stack, with a stack pointer pointing to the top of it and allocation and deallocation of stack frames and local variables happening throughout execution. Because memory is immutable, this cannot be done the usual way; once you allocate a new stack frame that memory is set, it can't be reused for another one later on. + +Because of this, memory in Cairo is divided into `segments`. This is just a way of organizing memory more conveniently for this write-once model. Each segment is nothing more than a contiguous memory region. Segments are identified by an `index`, an integer value that uniquely identifies them. + +Memory `cells` (i.e. values in memory) are identified by the index of the segment they belong to and an `offset` into said segment. Thus, the memory cell `{2,0}` is the first cell of segment number `2`. + +Even though this segment model is extremely convenient for the VM's execution, the STARK prover needs to have the memory as just one contiguous region. Because of this, once execution of a Cairo program finishes, all the memory segments are collapsed into one; this process is called `Relocation`. We will go into more detail on all of this below. + +The first segment (index 0) is the program segment, which stores the instructions of a cairo program. The following segment (index 1) is the execution segment, which holds the values that are created along the execution of the vm, for example, when we call a function, a pointer to the next instruction after the call instruction will be stored in the execution segment which will then be used to find the next instruction after the function returns. + +The following group of segments are the builtin segments, one for each builtin used by the program, and which hold values used by the builtin runners. + +The last group of segments are the user segments, which represent data structures created by the user, for example, when creating an array on a cairo program, that array will be represented in memory as its own segment. + +While memory is continous, some gaps may be present. These gaps can be created on purpose by the user, for example by executing the following CASM: + +```text +[ap + 1] = 2; +``` + +These gaps may also be created indireclty by diverging branches, as for example one branch may declare a variable that the other branch doesn't, as memory needs to be allocated for both cases if the second case is ran then a gap is left where the variable should have been written. + +### Felts + +Felts, or Field Elements, are cairo's basic integer type. Every variable in a cairo vm that is not a pointer is a felt. From our point of view we could say a felt in cairo is an unsigned integer in the range [0, P), where P is a very large prime currently equal to `2^251+17*2^192+1`. This means that all operations are done modulo P. + +### Relocatable + +An address (or pointer) in cairo is represented as a `Relocatable` value, which is made up of a `segment_index` and an `offset`, the `segment_index` tells us which segment the value is stored in and the `offset` tells us how many values exist between the start of the segment and the value. + +As the cairo memory can hold both felts and pointers, the basic memory unit is a `MaybeRelocatable`, a variable that can be either a `Relocatable` or a `Felt`. + +### Memory Relocation + +During execution, the memory consists of segments of varying length, and they can be accessed by indicating their segment index, and the offset within that segment. When the run is finished, a relocation process takes place, which transforms this segmented memory into a contiguous list of values. The relocation process works as follows: + +1. The size of each segment is calculated as the highest offset within the segment + 1. +2. A base is assigned to each segment by accumulating the size of the previous segment. The first segment's base is set to 1. +3. All `relocatable` values are converted into a single integer by adding their `offset` value to their segment's base calculated in the previous step + +For example, if we have this memory represented by address, value pairs: + +```text + 0:0 -> 1 + 0:1 -> 4 + 0:2 -> 7 + 1:0 -> 8 + 1:1 -> 0:2 + 1:4 -> 0:1 + 2:0 -> 1 +``` + +Then, to relocate: + +1. Calculate segment sizes: + ```text + 0 --(has size)--> 3 + 1 --(has size)--> 5 + 2 --(has size)--> 1 + ``` + +2. Assign a base to each segment: + ```text + 0 --(has base value)--> 1 + 1 --(has base value)--> 4 (that is: 1 + 3) + 2 --(has base value)--> 9 (that is: 4 + 5) + ``` + +3. Convert relocatables to integers + ```text + 1 (base[0] + 0) -> 1 + 2 (base[0] + 1) -> 4 + 3 (base[0] + 2) -> 7 + 4 (base[1] + 0) -> 8 + 5 (base[1] + 1) -> 3 (that is: base[0] + 2) + .... (memory gaps) + 8 (base[1] + 4) -> 2 (that is: base[0] + 1) + 9 (base[2] + 0) -> 1 + ``` + +## Instruction Set + +### Registers + +There are only three registers in the Cairo VM: + +- The program counter `pc`, which points to the next instruction to be executed. +- The allocation pointer `ap`, pointing to the next unused memory cell. +- The frame pointer `fp`, pointing to the base of the current stack frame. When a new function is called, `fp` is set to the current `ap`. When the function returns, `fp` goes back to its previous value. The VM creates new segments whenever dynamic allocation is needed, so for example the cairo analog to a Rust `Vec` will have its own segment. Relocation at the end meshes everything together. + +### Instruction Format + +CASM instruction have the following format. If the instruction uses an immediate operand, it's value is taken from the next cell of the program segment. + +``` +// Structure of the 63-bit that form the first word of each instruction. +// See Cairo whitepaper, page 32 - https://eprint.iacr.org/2021/1063.pdf. +┌─────────────────────────────────────────────────────────────────────────┐ +│ off_dst (biased representation) │ +├─────────────────────────────────────────────────────────────────────────┤ +│ off_op0 (biased representation) │ +├─────────────────────────────────────────────────────────────────────────┤ +│ off_op1 (biased representation) │ +├─────┬─────┬───────┬───────┬───────────┬────────┬───────────────────┬────┤ +│ dst │ op0 │ op1 │ res │ pc │ ap │ opcode │ 0 │ +│ reg │ reg │ src │ logic │ update │ update │ │ │ +├─────┼─────┼───┬───┼───┬───┼───┬───┬───┼───┬────┼────┬────┬────┬────┼────┤ +│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ 12 │ 13 │ 14 │ 15 │ +└─────┴─────┴───┴───┴───┴───┴───┴───┴───┴───┴────┴────┴────┴────┴────┴────┘ +``` + +- The first 6 fields: `off_dst`, `off_op0`, `off_op1`, `dst_reg`, `op0_reg`, `op1_src` determine the memory locations of the operands, and the destination of the result (which is not always used). + - `op1_src` occupies 2 bits, as it can also be an immediate, in which case the value will be taken from the next instruction (`[pc + 1]`). +- The `res_logic` field determines how to compute the result (op1, sum, multiplication). The usage of the result depends on the following fields. +- The `opcode` field describes which operation is been performed (noop, assert, call, ret). It modifies the meaning of the following fields. +- The `pc_update` field determines how to update the program counter (advance, jump, branch, etc.). +- The `ap_update` field determines how to update the allocation pointer. + +For an in-depth explanation, you can see Cairo whitepaper, page 33 - https://eprint.iacr.org/2021/1063.pdf, or checkout [our implementation](/vm/src/vm/vm_core.rs). + +Take, for example, the following instruction: + +``` +[ap + 1] = [fp + 2] + 3 +``` + +The instruction (at `[pc]`) will be encoded as: + +``` +off_dst = 1 +off_op0 = 2 +off_op1 = 1 # It's always 1 when op1 is an immediate +dst_reg = 0 # AP +op0_reg = 1 # FP +op1_src = 1 # Immediate +res_logic = 1 # Add +pc_update = 0 # Regular (advance) +ap_update = 0 # Regular (no update) +opcode = 4 # Assert +``` + +The next instruction (at `[pc + 1]`) will be the immediate, and it will have a value of `3`. + +Given the following initial register values: +``` +fp = 5 +ap = 10 +pc = 15 +``` +Then: +- `op1` is `[fp + 2]`, which is resolved to `[7]`. +- `op2` is `[pc + 1]`, which is resolved to `[16] == 3`. +- `dst` is `[ap + 1]`, which is resolved to `[11]` +- The result of `op1 + op2` is stored at `dst` +- The register `pc` is increased by 2, we skip the next instruction because it was the immediate. +- The register `fp` is not updated +- The register `ap` is not updated + +## Hints + +So far we have been thinking about the VM mostly abstracted from the prover and verifier it's meant to feed its results to. The last main feature we need to talk about, however, requires keeping this proving/verifying logic in mind. + +As a reminder, the whole point of the Cairo VM is to output a trace/memory file so that a `prover` can then create a cryptographic proof that the execution of the program was done correctly. A `verifier` can then take that proof and verify it in much less time than it would have taken to re-execute the entire program. + +In this model, the one actually using the VM to run a cairo program is *always the prover*. The verifier does not use the VM in any way, as that would defeat the entire purpose of validity proofs; they just get the program being run and the proof generated by the prover and run some cryptographic algorithm to check it. + +While the verifier does not execute the code, they do *check it*. As an example, if a cairo program computes a fibonacci number like this: + +``` +func main() { + // Call fib(1, 1, 10). + let result: felt = fib(1, 1, 10); +} +``` + +the verifier won't *run* this, but they will reject any incorrect execution of the call to `fib`. The correct value for `result` in this case is `144` (it's the 10th fibonacci number); any attempt by the prover to convince the verifier that `result` is not `144` will fail, because the call to the `fib` function is *being proven* and thus *seen* by the verifier. + +A `Hint` is a piece of code that is not proven, and therefore not seen by the verifier. If `fib` above were a hint, then the prover could convince the verifier that `result` is $144$, $0$, $1000$ or any other number. + +In cairo 0, hints are code written in `Python` and are surrounded by curly brackets. Here's an example from the `alloc` function, provided by the Cairo common library + +``` +func alloc() -> (ptr: felt*) { + %{ memory[ap] = segments.add() %} + ap += 1; + return (ptr=cast([ap - 1], felt*)); +} +``` + +The first line of the function, + +``` +%{ memory[ap] = segments.add() %} +``` + +is a hint called `ADD_SEGMENT`. All it does is create a new memory segment, then write its base to the current value of `ap`. This is python code that is being run in the context of the VM's execution; thus `memory` refers to the VM's current memory and `segments.add()` is just a function provided by the VM to allocate a new segment. + +At this point you might be wondering: why run code that's not being proven? Isn't the whole point of Cairo to prove correct execution? There are (at least) two reasons for hints to exist. + +### Nothing to prove + +For some operations there's simply nothing to prove, as they are just convenient things one wants to do during execution. The `ADD_SEGMENT` hint shown above is a good example of that. When proving execution, the program's memory is presented as one relocated continuous segment, it does not matter at all which segment a cell was in, or when that segment was added. The verifier doesn't care. + +Because of this, there's no reason to make `ADD_SEGMENT` a part of the cairo language and have an instruction for it. + +### Optimization + +Certain operations can be very expensive, in the sense that they might involve a huge amount of instructions or memory usage, and therefore contribute heavily to the proving time. For certain calculations, there are two ways to convince the verifier that it was done correctly: + +- Write the entire calculation in Cairo/Cairo Assembly. This makes it show up in the trace and therefore get proven. +- *Present the result of the calculation to the verifier through a hint*, then show said result indeed satisfies the relevant condition that makes it the actual result. + +To make this less abstract, let's show two examples. + +#### Square root + +Let's say the calculation in question is to compute the square root of a number `x`. The two ways to do it then become: + +- Write the usual square root algorithm in Cairo to compute `sqrt(x)`. +- Write a hint that computes `sqrt(x)`, then immediately after calling the hint show __in Cairo__ that `(sqrt(x))^2 = x`. + +The second approach is exactly what the `sqrt` function in the Cairo common library does: + +``` +// Returns the floor value of the square root of the given value. +// Assumptions: 0 <= value < 2**250. +func sqrt{range_check_ptr}(value) -> felt { + alloc_locals; + local root: felt; + + %{ + from starkware.python.math_utils import isqrt + value = ids.value % PRIME + assert value < 2 ** 250, f"value={value} is outside of the range [0, 2**250)." + assert 2 ** 250 < PRIME + ids.root = isqrt(value) + %} + + assert_nn_le(root, 2 ** 125 - 1); + tempvar root_plus_one = root + 1; + assert_in_range(value, root * root, root_plus_one * root_plus_one); + + return root; +} +``` + +If you read it carefully, you'll see that the hint in this function computes the square root in python, then this line + +``` +assert_in_range(value, root * root, root_plus_one * root_plus_one); +``` + +asserts __in Cairo__ that `(sqrt(x))^2 = x`. + +This is done this way because it is much cheaper, in terms of the generated trace (and thus proving time), to square a number than compute its square root. + +Notice that the last assert is absolutely mandatory to make this safe. If you forget to write it, the square root calculation does not get proven, and anyone could convince the verifier that the result of `sqrt(x)` is any number they like. + +#### Linear search turned into an O(1) lookup + +This example is taken from the [Cairo documentation](https://docs.cairo-lang.org/0.12.0/hello_cairo/program_input.html). + +Given a list of `(key, value)` pairs, if we want to write a `get_value_by_key` function that returns the value associated to a given key, there are two ways to do it: + +- Write a linear search in Cairo, iterating over each key until you find the requested one. +- Do that exact same linear search *inside a hint*, find the result, then show that the result's key is the one requested. + +Again, the second approach makes the resulting trace and proving much faster, because it's just a lookup; there's no linear search. Notice this only applies to proving, the VM has to execute the hint, so there's still a linear search when executing to generate the trace. In fact, the second approach is more expensive for the VM than the first one. It has to do both a linear search and a lookup. This is a tradeoff in favor of proving time. + +Also note that, as in the square root example, when writing this logic you need to remember to show the hint's result is the correct one in Cairo. If you don't, your code is not being proven. + +### Non-determinism + +The Cairo paper and documentation refers to this second approach to calculating things through hints as *non-determinism*. The reason for this is that sometimes there is more than one result that satisfies a certain condition. This means that cairo execution becomes non deterministic; a hint could output multiple values, and in principle there is no way to know which one it's going to be. Running the same code multiple times could give different results. + +The square root is an easy example of this. The condition `(sqrt(x))^2 = x` is not unique, there are two solutions to it. Without the hint, this is non-deterministic, `x` could have multiple values; the hint resolves that by choosing a specific value when being run. + +### Common Library and Hints + +As explained above, using hints in your code is highly unsafe. Forgetting to add a check after calling them can make your code vulnerable to any sorts of attacks, as your program will not prove what you think it proves. + +Because of this, most hints in Cairo 0 are wrapped around or used by functions in the Cairo common library that do the checks for you, thus making them safe to use. Ideally, Cairo developers should not be using hints on their own; only transparently through Cairo library functions they call. + +### Whitelisted Hints + +In Cairo, a hint could be any Python code you like. In the context of it as just another language someone might want to use, this is fine. In the context of Cairo as a programming language used to write smart contracts deployed on a blockchain, it's not. Users could deploy contracts with hints that simply do + +```python +while true: + pass +``` + +and grind the network down to a halt, as nodes get stuck executing an infinite loop when calling the contract. + +To address this, the starknet network maintains a list of *whitelisted* hints, which are the only ones that can be used in starknet contracts. These are the ones implemented in this VM. + +## Builtins + +A builtin is a low level optimization integrated into the core loop of the VM that allows otherwise expensive computation to be performed more efficiently. Builtins have two ways to operate: via validation rules and via auto-deduction rules. + +- Validation rules are applied to every element that is inserted into a builtin's segment. For example, if I want to verify an ecdsa signature, I can insert it into the ecdsa builtin's segment and let a validation rule take care of verifying the signature. +- Auto-deduction rules take over during instruction execution, when we can't compute the value of an operand who's address belongs to a builtin segment, we can use that builtin's auto-deduction rule to calculate the value of the operand. For example, If I want to calculate the pedersen hash of two values, I can write the values into the pedersen builtin's segment and then ask for the next memory cell, without builtins, this instruction would have failed, as there is no value stored in that cell, but now we can use auto-deduction rules to calculate the hash and fill in that memory cell. + +## Program parsing + +The input of the Virtual Machine is a compiled Cairo program in Json format. The main parts of the file are listed below: + +- **data:** List of hexadecimal values that represent the instructions and immediate values defined in the cairo program. Each hexadecimal value is stored as a maybe_relocatable element in memory, but they can only be felts because the decoder has to be able to get the instruction fields in its bit representation. +- **debug_info:** This field provides information about the instructions defined in the data list. Each one is identified with its index inside the data list. For each one it contains information about the cairo variables in scope, the hints executed before that instruction if any, and its location inside the cairo program. +- **hints:** All the hints used in the program, ordered by the pc offset at which they should be executed. +- **identifiers:** User-defined symbols in the Cairo code representing variables, functions, classes, etc. with unique names. The expected offset, type and its corresponding information is provided for each identifier + + For example, the identifier representing the main function (usually the entrypoint of the program) is of `function` type, and a list of decorators wrappers (if there are any) are provided as additional information. + Another example is a user defined struct, is of `struct` type, it provides its size, the members it contains (with its information) and more. + +- **main_scope:** Usually something like `__main__`. All the identifiers associated with main function will be identified as `__main__`.identifier_name. Useful to identify the entrypoint of the program. +- **prime:** The cairo prime in hexadecimal format. As explained above, all arithmetic operations are done over a base field, modulo this primer number. +- **reference_manager:** Contains information about cairo variables. This information is useful to access to variables when executing cairo hints. + +# Code Walkthrough + +If you want a step by step guide on how to implement your own VM you can read our [code walkthrough in Go](https://github.com/lambdaclass/cairo-vm_in_go?tab=readme-ov-file#code-walkthroughwrite-your-own-cairo-vm)