From e5068d4676eaabec04b3a6235ad0bfc20e0ee484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s?= <47506558+MegaRedHand@users.noreply.github.com> Date: Mon, 17 Apr 2023 17:36:56 -0300 Subject: [PATCH 1/2] feat(hints): add NewHint#25 and NewHint#24 (#994) * Add NewHint#26 * Update changelog * Change assert_matches for assert + is_ok * Get and insert SECP_P from scope where applicable * Add NewHint#25 * Add NewHint#24 * Update changelog * Appease clippy * Rename hint codes * Get or insert N from scope * Change test contract * Fix test * Fix test (for real this time) --- CHANGELOG.md | 16 +++ cairo_programs/div_mod_n.cairo | 129 ++++++++++++++++++ .../builtin_hint_processor_definition.rs | 17 ++- .../builtin_hint_processor/hint_code.rs | 12 +- .../builtin_hint_processor/secp/signature.rs | 81 +++++++---- src/tests/cairo_run_test.rs | 7 + 6 files changed, 232 insertions(+), 30 deletions(-) create mode 100644 cairo_programs/div_mod_n.cairo diff --git a/CHANGELOG.md b/CHANGELOG.md index a09ff06ad4..e6e11d7e2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,22 @@ * Added dynamic layout [#879](https://github.com/lambdaclass/cairo-rs/pull/879) * `get_segment_size` was exposed [#934](https://github.com/lambdaclass/cairo-rs/pull/934) +* Add missing hints on cairo_secp lib [#994](https://github.com/lambdaclass/cairo-rs/pull/994):: + + `BuiltinHintProcessor` now supports the following hints: + ```python + from starkware.cairo.common.cairo_secp.secp_utils import pack + from starkware.python.math_utils import div_mod, safe_div + + a = pack(ids.a, PRIME) + b = pack(ids.b, PRIME) + value = res = div_mod(a, b, N) + ``` + + ```python + value = k_plus_one = safe_div(res * b - a, N) + 1 + ``` + * Add missing hint on cairo_secp lib [#992](https://github.com/lambdaclass/cairo-rs/pull/992): `BuiltinHintProcessor` now supports the following hint: diff --git a/cairo_programs/div_mod_n.cairo b/cairo_programs/div_mod_n.cairo new file mode 100644 index 0000000000..4dbe3c8290 --- /dev/null +++ b/cairo_programs/div_mod_n.cairo @@ -0,0 +1,129 @@ +%builtins range_check + +from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul +from starkware.cairo.common.cairo_secp.constants import BETA, N0, N1, N2 + +// Source: https://github.com/myBraavos/efficient-secp256r1/blob/73cca4d53730cb8b2dcf34e36c7b8f34b96b3230/src/secp256r1/signature.cairo + +// Computes a * b^(-1) modulo the size of the elliptic curve (N). +// +// Prover assumptions: +// * All the limbs of a are in the range (-2 ** 210.99, 2 ** 210.99). +// * All the limbs of b are in the range (-2 ** 124.99, 2 ** 124.99). +// * b is in the range [0, 2 ** 256). +// +// Soundness assumptions: +// * The limbs of a are in the range (-2 ** 249, 2 ** 249). +// * The limbs of b are in the range (-2 ** 159.83, 2 ** 159.83). +func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) { + %{ + from starkware.cairo.common.cairo_secp.secp_utils import N, pack + from starkware.python.math_utils import div_mod, safe_div + + a = pack(ids.a, PRIME) + b = pack(ids.b, PRIME) + value = res = div_mod(a, b, N) + %} + let (res) = nondet_bigint3(); + + %{ value = k_plus_one = safe_div(res * b - a, N) + 1 %} + let (k_plus_one) = nondet_bigint3(); + let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2); + + let (res_b) = bigint_mul(res, b); + let n = BigInt3(N0, N1, N2); + let (k_n) = bigint_mul(k, n); + + // We should now have res_b = k_n + a. Since the numbers are in unreduced form, + // we should handle the carry. + + tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE; + assert [range_check_ptr + 0] = carry1 + 2 ** 127; + + tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE; + assert [range_check_ptr + 1] = carry2 + 2 ** 127; + + tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE; + assert [range_check_ptr + 2] = carry3 + 2 ** 127; + + tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE; + assert [range_check_ptr + 3] = carry4 + 2 ** 127; + + assert res_b.d4 - k_n.d4 + carry4 = 0; + + let range_check_ptr = range_check_ptr + 4; + + return (res=res); +} + +func div_mod_n_alt{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) { + // just used to import N + %{ + from starkware.cairo.common.cairo_secp.secp_utils import N, pack + from starkware.python.math_utils import div_mod, safe_div + + a = pack(ids.a, PRIME) + b = pack(ids.b, PRIME) + value = res = div_mod(a, b, N) + %} + + %{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + from starkware.python.math_utils import div_mod, safe_div + + a = pack(ids.a, PRIME) + b = pack(ids.b, PRIME) + value = res = div_mod(a, b, N) + %} + let (res) = nondet_bigint3(); + + %{ value = k_plus_one = safe_div(res * b - a, N) + 1 %} + let (k_plus_one) = nondet_bigint3(); + let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2); + + let (res_b) = bigint_mul(res, b); + let n = BigInt3(N0, N1, N2); + let (k_n) = bigint_mul(k, n); + + tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE; + assert [range_check_ptr + 0] = carry1 + 2 ** 127; + + tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE; + assert [range_check_ptr + 1] = carry2 + 2 ** 127; + + tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE; + assert [range_check_ptr + 2] = carry3 + 2 ** 127; + + tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE; + assert [range_check_ptr + 3] = carry4 + 2 ** 127; + + assert res_b.d4 - k_n.d4 + carry4 = 0; + + let range_check_ptr = range_check_ptr + 4; + + return (res=res); +} + +func test_div_mod_n{range_check_ptr: felt}() { + let a: BigInt3 = BigInt3(100, 99, 98); + let b: BigInt3 = BigInt3(10, 9, 8); + + let (res) = div_mod_n(a, b); + + assert res = BigInt3( + 3413472211745629263979533, 17305268010345238170172332, 11991751872105858217578135 + ); + + // test alternative hint + let (res_alt) = div_mod_n_alt(a, b); + + assert res_alt = res; + + return (); +} + +func main{range_check_ptr: felt}() { + test_div_mod_n(); + + return (); +} diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index 7383370e99..5dc58ab18c 100644 --- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -38,8 +38,8 @@ use crate::{ verify_zero, verify_zero_with_external_const, }, signature::{ - div_mod_n_packed_divmod, div_mod_n_safe_div, get_point_from_x, - pack_modn_div_modn, + div_mod_n_packed_divmod, div_mod_n_packed_external_n, div_mod_n_safe_div, + get_point_from_x, pack_modn_div_modn, }, }, segments::{relocate_segment, temporary_array}, @@ -350,13 +350,20 @@ impl HintProcessor for BuiltinHintProcessor { } hint_code::IS_ZERO_NONDET => is_zero_nondet(vm, exec_scopes), hint_code::IS_ZERO_ASSIGN_SCOPE_VARS => is_zero_assign_scope_variables(exec_scopes), - hint_code::DIV_MOD_N_PACKED_DIVMOD => div_mod_n_packed_divmod( + hint_code::DIV_MOD_N_PACKED_DIVMOD_V1 => div_mod_n_packed_divmod( vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, ), - hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b"), + hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N => div_mod_n_packed_external_n( + vm, + exec_scopes, + &hint_data.ids_data, + &hint_data.ap_tracking, + ), + hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b", 0), + hint_code::DIV_MOD_N_SAFE_DIV_PLUS_ONE => div_mod_n_safe_div(exec_scopes, "a", "b", 1), hint_code::GET_POINT_FROM_X => get_point_from_x( vm, exec_scopes, @@ -493,7 +500,7 @@ impl HintProcessor for BuiltinHintProcessor { hint_code::PACK_MODN_DIV_MODN => { pack_modn_div_modn(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } - hint_code::XS_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "x", "s"), + hint_code::XS_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "x", "s", 0), hint_code::UINT384_UNSIGNED_DIV_REM => { uint384_unsigned_div_rem(vm, &hint_data.ids_data, &hint_data.ap_tracking) } diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 6131ead533..872a6ec5cf 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -440,7 +440,14 @@ from starkware.python.math_utils import div_mod value = x_inv = div_mod(1, x, SECP_P)"#; -pub const DIV_MOD_N_PACKED_DIVMOD: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import N, pack +pub const DIV_MOD_N_PACKED_DIVMOD_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import N, pack +from starkware.python.math_utils import div_mod, safe_div + +a = pack(ids.a, PRIME) +b = pack(ids.b, PRIME) +value = res = div_mod(a, b, N)"#; + +pub const DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack from starkware.python.math_utils import div_mod, safe_div a = pack(ids.a, PRIME) @@ -449,6 +456,9 @@ value = res = div_mod(a, b, N)"#; pub const DIV_MOD_N_SAFE_DIV: &str = r#"value = k = safe_div(res * b - a, N)"#; +pub const DIV_MOD_N_SAFE_DIV_PLUS_ONE: &str = + r#"value = k_plus_one = safe_div(res * b - a, N) + 1"#; + pub const GET_POINT_FROM_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack x_cube_int = pack(ids.x_cube, PRIME) % SECP_P diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs index 84dd9e5979..54b13b0bf4 100644 --- a/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -1,7 +1,5 @@ -use crate::any_box; -use crate::stdlib::{collections::HashMap, ops::Shr, prelude::*}; - use crate::{ + any_box, hint_processor::{ builtin_hint_processor::{ hint_utils::get_integer_from_var_name, @@ -11,10 +9,11 @@ use crate::{ }, math_utils::{div_mod, safe_div_bigint}, serde::deserialize_program::ApTracking, + stdlib::{collections::HashMap, ops::Shr, prelude::*}, types::exec_scope::ExecutionScopes, - vm::errors::hint_errors::HintError, - vm::vm_core::VirtualMachine, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; +use core::ops::Add; use felt::Felt252; use num_bigint::BigInt; use num_integer::Integer; @@ -32,16 +31,17 @@ a = pack(ids.a, PRIME) b = pack(ids.b, PRIME) value = res = div_mod(a, b, N) */ -pub fn div_mod_n_packed_divmod( +pub fn div_mod_n_packed( vm: &mut VirtualMachine, exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, + n: &BigInt, ) -> Result<(), HintError> { let a = pack(BigInt3::from_var_name("a", vm, ids_data, ap_tracking)?); let b = pack(BigInt3::from_var_name("b", vm, ids_data, ap_tracking)?); - let value = div_mod(&a, &b, &N); + let value = div_mod(&a, &b, n); exec_scopes.insert_value("a", a); exec_scopes.insert_value("b", b); exec_scopes.insert_value("value", value.clone()); @@ -49,18 +49,39 @@ pub fn div_mod_n_packed_divmod( Ok(()) } +pub fn div_mod_n_packed_divmod( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + exec_scopes.assign_or_update_variable("N", any_box!(N.clone())); + div_mod_n_packed(vm, exec_scopes, ids_data, ap_tracking, &N) +} + +pub fn div_mod_n_packed_external_n( + vm: &mut VirtualMachine, + exec_scopes: &mut ExecutionScopes, + ids_data: &HashMap, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + let n = exec_scopes.get::("N")?; + div_mod_n_packed(vm, exec_scopes, ids_data, ap_tracking, &n) +} + // Implements hint: // value = k = safe_div(res * b - a, N) pub fn div_mod_n_safe_div( exec_scopes: &mut ExecutionScopes, a_alias: &str, b_alias: &str, + to_add: u64, ) -> Result<(), HintError> { let a = exec_scopes.get_ref::(a_alias)?; let b = exec_scopes.get_ref::(b_alias)?; let res = exec_scopes.get_ref::("res")?; - let value = safe_div_bigint(&(res * b - a), &N)?; + let value = safe_div_bigint(&(res * b - a), &N)?.add(to_add); exec_scopes.insert_value("value", value); Ok(()) @@ -163,22 +184,33 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn safe_div_ok() { - let hint_code = hint_code::DIV_MOD_N_PACKED_DIVMOD; - let mut vm = vm!(); + // "import N" + let mut exec_scopes = ExecutionScopes::new(); + exec_scopes.assign_or_update_variable("N", any_box!(N.clone())); - vm.segments = segments![ - ((1, 0), 15), - ((1, 1), 3), - ((1, 2), 40), - ((1, 3), 0), - ((1, 4), 10), - ((1, 5), 1) + let hint_codes = vec![ + hint_code::DIV_MOD_N_PACKED_DIVMOD_V1, + hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N, ]; - vm.run_context.fp = 3; - let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)]; - let mut exec_scopes = ExecutionScopes::new(); - assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); - assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b"), Ok(())); + for hint_code in hint_codes { + let mut vm = vm!(); + + vm.segments = segments![ + ((1, 0), 15), + ((1, 1), 3), + ((1, 2), 40), + ((1, 3), 0), + ((1, 4), 10), + ((1, 5), 1) + ]; + vm.run_context.fp = 3; + let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)]; + + assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); + + assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 0), Ok(())); + assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 1), Ok(())); + } } #[test] @@ -193,7 +225,8 @@ mod tests { div_mod_n_safe_div( &mut exec_scopes, "a", - "b" + "b", + 0, ), Err( HintError::Math(MathError::SafeDivFailBigInt( @@ -290,6 +323,6 @@ mod tests { let ids_data = non_continuous_ids_data![("x", -3), ("s", 0)]; let mut exec_scopes = ExecutionScopes::new(); assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(())); - assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "x", "s"), Ok(())); + assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "x", "s", 0), Ok(())); } } diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index 9429dd94ae..465d51e8f0 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -1322,3 +1322,10 @@ fn cairo_run_efficient_secp256r1_ec() { let program_data = include_bytes!("../../cairo_programs/efficient_secp256r1_ec.json"); run_program_simple(program_data.as_slice()); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn cairo_run_div_mod_n() { + let program_data = include_bytes!("../../cairo_programs/div_mod_n.json"); + run_program_simple(program_data.as_slice()); +} From a9933181fccde616d5fd9599fdddf64886057329 Mon Sep 17 00:00:00 2001 From: Mario Rugiero Date: Mon, 17 Apr 2023 17:47:51 -0300 Subject: [PATCH 2/2] perf: add benchmarks for runner construction (#995) * perf: add benchmarks for runner construction - IAI and Criterion benchmarks for constructing 100 `CairoRunner` instances from a single `Program` instance. - IAI and Criterion benchmark for `Program` parsing as baseline. - Remove old criterion benchmarks for whole programs, they've been superseded by Hyperfine and have very high cost/benefit ratio. * perf: delete whole-program benchmarks from IAI * ci: re-enable IAI workflow --- .github/workflows/iai_pr.yml | 4 + bench/criterion_benchmark.rs | 90 ++++++++-------------- bench/iai_benchmark.rs | 144 +++++------------------------------ 3 files changed, 52 insertions(+), 186 deletions(-) diff --git a/.github/workflows/iai_pr.yml b/.github/workflows/iai_pr.yml index c2d6c3dd64..727480956b 100644 --- a/.github/workflows/iai_pr.yml +++ b/.github/workflows/iai_pr.yml @@ -1,5 +1,9 @@ name: benchmark_pr +on: + pull_request: + branches: [ '*' ] + jobs: fetch-iai-results: runs-on: ubuntu-22.04 diff --git a/bench/criterion_benchmark.rs b/bench/criterion_benchmark.rs index 1e2d819e2f..2f50c13493 100644 --- a/bench/criterion_benchmark.rs +++ b/bench/criterion_benchmark.rs @@ -1,9 +1,4 @@ -use std::path::Path; - -use cairo_vm::{ - cairo_run, - hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, -}; +use cairo_vm::{types::program::Program, vm::runners::cairo_runner::CairoRunner}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; #[cfg(feature = "with_mimalloc")] @@ -13,61 +8,36 @@ use mimalloc::MiMalloc; #[global_allocator] static ALLOC: MiMalloc = MiMalloc; -const BENCH_NAMES: &[&str] = &[ - "compare_arrays_200000", - "factorial_multirun", - "fibonacci_1000_multirun", - "integration_builtins", - "linear_search", - "keccak_integration_benchmark", - "secp_integration_benchmark", - "blake2s_integration_benchmark", - "dict_integration_benchmark", - "math_integration_benchmark", - "memory_integration_benchmark", - "math_cmp_and_pow_integration_benchmark", - "operations_with_data_structures_benchmarks", - "uint256_integration_benchmark", - "set_integration_benchmark", - "poseidon_integration_benchmark", - "pedersen", -]; -const BENCH_PATH: &str = "cairo_programs/benchmarks/"; - -pub fn criterion_benchmarks(c: &mut Criterion) { - let mut hint_executor = BuiltinHintProcessor::new_empty(); - let cairo_run_config = cairo_vm::cairo_run::CairoRunConfig { - layout: "all_cairo", - ..cairo_vm::cairo_run::CairoRunConfig::default() - }; - for benchmark_name in build_bench_strings() { - let file_content = std::fs::read(Path::new(&benchmark_name.1)).unwrap(); - c.bench_function(&benchmark_name.0, |b| { - b.iter(|| { - cairo_run::cairo_run( - black_box(&file_content), - &cairo_run_config, - &mut hint_executor, - ) - }) - }); - } +fn parse_program(c: &mut Criterion) { + //Picked the biggest one at the time of writing + let program = include_bytes!("../cairo_programs/benchmarks/keccak_integration_benchmark.json"); + c.bench_function("parse program", |b| { + b.iter(|| { + _ = Program::from_bytes(black_box(program.as_slice()), black_box(Some("main"))) + .unwrap(); + }) + }); } -fn build_bench_strings() -> Vec<(String, String)> { - let mut full_string = Vec::<(String, String)>::new(); - - for filename in BENCH_NAMES { - let file_no_extension = String::from(*filename); - let file_extension = String::from(".json"); - let bench_path = String::from(BENCH_PATH); - let full_file_path = bench_path + &file_no_extension + &file_extension; - let cairo_call = format!("cairo_run({})", &full_file_path); - full_string.push((cairo_call, full_file_path)); - } - - full_string +fn build_many_runners(c: &mut Criterion) { + //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(); + c.bench_function("build runner", |b| { + b.iter(|| { + for _ in 0..100 { + _ = black_box( + CairoRunner::new( + black_box(&program), + black_box("starknet_with_keccak"), + black_box(false), + ) + .unwrap(), + ); + } + }) + }); } -criterion_group!(benches, criterion_benchmarks); -criterion_main!(benches); +criterion_group!(runner, parse_program, build_many_runners); +criterion_main!(runner); diff --git a/bench/iai_benchmark.rs b/bench/iai_benchmark.rs index f641fb43a9..02b658bd61 100644 --- a/bench/iai_benchmark.rs +++ b/bench/iai_benchmark.rs @@ -1,50 +1,6 @@ -use std::{ - fs::File, - io, - io::{BufWriter, Write}, -}; - -use bincode::enc::write::Writer; use iai::{black_box, main}; -use cairo_vm::{ - cairo_run::*, - hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor, -}; - -// Copied from the CLI -struct FileWriter { - buf_writer: BufWriter, - bytes_written: usize, -} - -impl Writer for FileWriter { - fn write(&mut self, bytes: &[u8]) -> Result<(), bincode::error::EncodeError> { - self.buf_writer - .write_all(bytes) - .map_err(|e| bincode::error::EncodeError::Io { - inner: e, - index: self.bytes_written, - })?; - - self.bytes_written += bytes.len(); - - Ok(()) - } -} - -impl FileWriter { - fn new(buf_writer: BufWriter) -> Self { - Self { - buf_writer, - bytes_written: 0, - } - } - - fn flush(&mut self) -> Result<(), io::Error> { - self.buf_writer.flush() - } -} +use cairo_vm::{types::program::Program, vm::runners::cairo_runner::CairoRunner}; #[cfg(feature = "with_mimalloc")] use mimalloc::MiMalloc; @@ -53,87 +9,23 @@ use mimalloc::MiMalloc; #[global_allocator] static ALLOC: MiMalloc = MiMalloc; -macro_rules! iai_bench_expand_prog { - ($val: ident) => { - fn $val() { - let cairo_run_config = cairo_vm::cairo_run::CairoRunConfig { - trace_enabled: true, - layout: "all_cairo", - //FIXME: we need to distinguish the proof compiled programs - //proof_mode: true, - secure_run: Some(true), - ..cairo_vm::cairo_run::CairoRunConfig::default() - }; - let mut hint_executor = BuiltinHintProcessor::new_empty(); - - let program = include_bytes!(concat!( - "../cairo_programs/benchmarks/", - stringify!($val), - ".json" - )); - let (runner, mut vm) = - cairo_run(black_box(program), &cairo_run_config, &mut hint_executor) - .expect("cairo_run failed"); - - let trace_file = File::create("/dev/null").expect("open trace file"); - let mut trace_writer = FileWriter::new(BufWriter::new(trace_file)); - let relocated_trace = vm.get_relocated_trace().expect("relocation failed"); - write_encoded_trace( - black_box(relocated_trace.as_slice()), - black_box(&mut trace_writer), - ) - .expect("writing execution trace failed"); - trace_writer.flush().expect("flush trace"); - - let memory_file = File::create("/dev/null").expect("open memory file"); - let mut memory_writer = FileWriter::new(BufWriter::new(memory_file)); - write_encoded_memory( - black_box(&runner.relocated_memory), - black_box(&mut memory_writer), - ) - .expect("writing relocated memory failed"); - memory_writer.flush().expect("flush memory"); - - vm.write_output(black_box(&mut String::new())) - .expect("writing output failed"); - } - }; +fn parse_program() { + //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(black_box(program.as_slice()), black_box(Some("main"))).unwrap(); + let _ = black_box(program); } -iai_bench_expand_prog! {math_integration_benchmark} -iai_bench_expand_prog! {compare_arrays_200000} -iai_bench_expand_prog! {factorial_multirun} -iai_bench_expand_prog! {fibonacci_1000_multirun} -iai_bench_expand_prog! {integration_builtins} -iai_bench_expand_prog! {linear_search} -iai_bench_expand_prog! {keccak_integration_benchmark} -iai_bench_expand_prog! {secp_integration_benchmark} -iai_bench_expand_prog! {blake2s_integration_benchmark} -iai_bench_expand_prog! {dict_integration_benchmark} -iai_bench_expand_prog! {memory_integration_benchmark} -iai_bench_expand_prog! {math_cmp_and_pow_integration_benchmark} -iai_bench_expand_prog! {operations_with_data_structures_benchmarks} -iai_bench_expand_prog! {uint256_integration_benchmark} -iai_bench_expand_prog! {set_integration_benchmark} -iai_bench_expand_prog! {poseidon_integration_benchmark} -iai_bench_expand_prog! {pedersen} +fn build_many_runners() { + //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(black_box(program.as_slice()), black_box(Some("main"))).unwrap(); + for _ in 0..100 { + let runner = CairoRunner::new(black_box(&program), "starknet_with_keccak", false).unwrap(); + let _ = black_box(runner); + } +} -main!( - math_integration_benchmark, - compare_arrays_200000, - factorial_multirun, - fibonacci_1000_multirun, - integration_builtins, - linear_search, - keccak_integration_benchmark, - secp_integration_benchmark, - blake2s_integration_benchmark, - dict_integration_benchmark, - memory_integration_benchmark, - math_cmp_and_pow_integration_benchmark, - operations_with_data_structures_benchmarks, - uint256_integration_benchmark, - set_integration_benchmark, - poseidon_integration_benchmark, - pedersen, -); +main!(parse_program, build_many_runners,);