From ca3b8abf51a4dbc6682d2cc75c2bc4327c324f05 Mon Sep 17 00:00:00 2001 From: fmoletta <99273364+fmoletta@users.noreply.github.com> Date: Tue, 9 Apr 2024 19:12:48 -0300 Subject: [PATCH] Add range_check96 builtin (#1698) * Admit both types of range_check in range_check_builtin_runner * Add range_check96 to layout + make bound a constant * Clippy * Add specialized constructors & remove n_parts field from instance def * Add changelog entry * fmt * Use const generic to differentiate between RangeCheck and RangeCheck96 * Fix * fmt * Update relocated ptr values to account for added segment * Fix --- CHANGELOG.md | 8 ++ cairo1-run/src/cairo_run.rs | 1 + fuzzer/Cargo.lock | 66 ++++------- .../builtin_hint_processor/math_utils.rs | 63 ++++------ .../squash_dict_utils.rs | 5 +- vm/src/serde/deserialize_program.rs | 3 + .../builtins_instance_def.rs | 17 ++- .../range_check_instance_def.rs | 44 +------ vm/src/utils.rs | 7 +- vm/src/vm/runners/builtin_runner/mod.rs | 106 +++++++++++++---- vm/src/vm/runners/builtin_runner/modulo.rs | 24 ++-- .../vm/runners/builtin_runner/range_check.rs | 109 +++++++++++------- vm/src/vm/runners/cairo_runner.rs | 36 ++++-- vm/src/vm/vm_core.rs | 5 +- vm/src/vm/vm_memory/memory.rs | 12 +- 15 files changed, 279 insertions(+), 227 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0471580ad1..91ef388a56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ #### Upcoming Changes +* feat(BREAKING): Add range_check96 builtin[#1698](https://github.com/lambdaclass/cairo-vm/pull/1698) + * Add the new `range_check96` builtin to the `all_cairo` layout. + * `RangeCheckBuiltinRunner` changes: + * Remove field `n_parts`, replacing it with const generic `N_PARTS`. + * Remome `n_parts` argument form method `new`. + * Remove field `_bound`, replacing it with public method `bound`. + * Add public methods `name` & `n_parts`. + * feat(BREAKING): Add mod builtin [#1673](https://github.com/lambdaclass/cairo-vm/pull/1673) Main Changes: diff --git a/cairo1-run/src/cairo_run.rs b/cairo1-run/src/cairo_run.rs index 47d1f5bbdb..8477eb7d88 100644 --- a/cairo1-run/src/cairo_run.rs +++ b/cairo1-run/src/cairo_run.rs @@ -499,6 +499,7 @@ fn create_entry_code( BuiltinName::keccak | BuiltinName::ecdsa | BuiltinName::output + | BuiltinName::range_check96 | BuiltinName::add_mod | BuiltinName::mul_mod => return fp_loc, }; diff --git a/fuzzer/Cargo.lock b/fuzzer/Cargo.lock index 7d61c3263c..b48dfec845 100644 --- a/fuzzer/Cargo.lock +++ b/fuzzer/Cargo.lock @@ -210,7 +210,7 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "1.0.0-rc0" +version = "1.0.0-rc1" dependencies = [ "anyhow", "arbitrary", @@ -221,7 +221,6 @@ dependencies = [ "hex", "keccak", "lazy_static", - "mimalloc", "nom", "num-bigint", "num-integer", @@ -520,13 +519,26 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "lambdaworks-crypto" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d4c222d5b2fdc0faf702d3ab361d14589b097f40eac9dc550e27083483edc65" +dependencies = [ + "lambdaworks-math", + "serde", + "sha2", + "sha3", +] + [[package]] name = "lambdaworks-math" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6c4d0ddd1fcd235be5196b1bcc404f89ad3e911f4c190fa01459e05dbf40f8" +checksum = "9ee7dcab3968c71896b8ee4dc829147acc918cffe897af6265b1894527fe3add" dependencies = [ - "thiserror", + "serde", + "serde_json", ] [[package]] @@ -555,16 +567,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "libmimalloc-sys" -version = "0.1.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "lock_api" version = "0.4.11" @@ -614,15 +616,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "mimalloc" -version = "0.1.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" -dependencies = [ - "libmimalloc-sys", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1078,12 +1071,13 @@ dependencies = [ [[package]] name = "starknet-types-core" -version = "0.0.6" +version = "0.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b6b868f545d43b474c2c00e9349c489fdeb7ff17eb00cdf339744ac4cae0930" +checksum = "6d53160556d1f23425100f42b3230df747ea05763efee685a2cd939dfb640701" dependencies = [ "arbitrary", "bitvec", + "lambdaworks-crypto", "lambdaworks-math", "lazy_static", "num-bigint", @@ -1132,26 +1126,6 @@ version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" -[[package]] -name = "thiserror" -version = "1.0.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3de26b0965292219b4287ff031fcba86837900fe9cd2b34ea8ad893c0953d2" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "268026685b2be38d7103e9e507c938a1fcb3d7e6eb15e87870b617bf37b6d581" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - [[package]] name = "thiserror-impl-no-std" version = "2.0.2" 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 fdfffb4485..a0fa71dddb 100644 --- a/vm/src/hint_processor/builtin_hint_processor/math_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/math_utils.rs @@ -45,13 +45,9 @@ pub fn is_nn( ap_tracking: &ApTracking, ) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; - let range_check_builtin = vm.get_range_check_builtin()?; + let range_check_bound = vm.get_range_check_builtin()?.bound(); //Main logic (assert a is not negative and within the expected range) - let value = match &range_check_builtin._bound { - Some(bound) if a.as_ref() >= bound => Felt252::ONE, - _ => Felt252::ZERO, - }; - insert_value_into_ap(vm, value) + insert_value_into_ap(vm, Felt252::from(a.as_ref() >= range_check_bound)) } //Implements hint: memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1 @@ -62,15 +58,9 @@ pub fn is_nn_out_of_range( ) -> Result<(), HintError> { let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?; let a = a.as_ref(); - let range_check_builtin = vm.get_range_check_builtin()?; + let range_check_bound = vm.get_range_check_builtin()?.bound(); //Main logic (assert a is not negative and within the expected range) - //let value = if (-a - 1usize).mod_floor(vm.get_prime()) < range_check_builtin._bound { - let value = match &range_check_builtin._bound { - Some(bound) if Felt252::ZERO - (a + 1u64) < *bound => Felt252::ZERO, - None => Felt252::ZERO, - _ => Felt252::ONE, - }; - insert_value_into_ap(vm, value) + insert_value_into_ap(vm, Felt252::from(-(a + 1) >= *range_check_bound)) } /* Implements hint:from starkware.cairo.common.math_utils import assert_integer %{ @@ -178,8 +168,8 @@ pub fn assert_le_felt_v_0_8( if a > b { return Err(HintError::NonLeFelt252(Box::new((*a, *b)))); } - let bound = vm.get_range_check_builtin()?._bound.unwrap_or_default(); - let small_inputs = Felt252::from((a < &bound && b - a < bound) as u8); + let bound = vm.get_range_check_builtin()?.bound(); + let small_inputs = Felt252::from((a < bound && b - a < *bound) as u8); insert_value_from_var_name("small_inputs", small_inputs, vm, ids_data, ap_tracking) } @@ -292,9 +282,10 @@ pub fn assert_nn( let range_check_builtin = vm.get_range_check_builtin()?; // assert 0 <= ids.a % PRIME < range_check_builtin.bound // as prime > 0, a % prime will always be > 0 - match &range_check_builtin._bound { - Some(bound) if a.as_ref() >= bound => Err(HintError::AssertNNValueOutOfRange(Box::new(a))), - _ => Ok(()), + if a.as_ref() >= range_check_builtin.bound() { + Err(HintError::AssertNNValueOutOfRange(Box::new(a))) + } else { + Ok(()) } } @@ -372,12 +363,9 @@ pub fn is_positive( // Avoid using abs so we don't allocate a new BigInt let (sign, abs_value) = value_as_int.into_parts(); //Main logic (assert a is positive) - match &range_check_builtin._bound { - Some(bound) if abs_value > bound.to_biguint() => { - return Err(HintError::ValueOutsideValidRange(Box::new(value))) - } - _ => {} - }; + if abs_value >= range_check_builtin.bound().to_biguint() { + return Err(HintError::ValueOutsideValidRange(Box::new(value))); + } let result = Felt252::from((sign == Sign::Plus) as u8); insert_value_from_var_name("is_positive", result, vm, ids_data, ap_tracking) @@ -460,7 +448,7 @@ pub fn signed_div_rem( let bound = get_integer_from_var_name("bound", vm, ids_data, ap_tracking)?; let builtin = vm.get_range_check_builtin()?; - let builtin_bound = &builtin._bound.unwrap_or(Felt252::MAX); + let builtin_bound = builtin.bound(); if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? { return Err(HintError::OutOfValidRange(Box::new((div, *builtin_bound)))); } @@ -511,22 +499,11 @@ pub fn unsigned_div_rem( ) -> Result<(), HintError> { let div = get_integer_from_var_name("div", vm, ids_data, ap_tracking)?; let value = get_integer_from_var_name("value", vm, ids_data, ap_tracking)?; - let builtin = vm.get_range_check_builtin()?; + let builtin_bound = vm.get_range_check_builtin()?.bound(); // Main logic - match &builtin._bound { - Some(builtin_bound) - if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? => - { - return Err(HintError::OutOfValidRange(Box::new((div, *builtin_bound)))); - } - None if div.is_zero() => { - return Err(HintError::OutOfValidRange(Box::new(( - div, - Felt252::ZERO - Felt252::ONE, - )))); - } - _ => {} + if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? { + return Err(HintError::OutOfValidRange(Box::new((div, *builtin_bound)))); } let (q, r) = value.div_rem(&(div).try_into().map_err(|_| MathError::DividedByZero)?); @@ -1807,9 +1784,9 @@ mod tests { //Initialize fp vm.run_context.fp = 6; //Insert ids into memory - let bound = vm.get_range_check_builtin().unwrap()._bound; + let bound = vm.get_range_check_builtin().unwrap().bound(); vm.segments = segments![((1, 3), (5)), ((1, 4), 10)]; - vm.insert_value((1, 5).into(), bound.unwrap()).unwrap(); + vm.insert_value((1, 5).into(), bound).unwrap(); //Create ids let ids_data = ids_data!["r", "biased_q", "range_check_ptr", "div", "value", "bound"]; //Execute the hint @@ -1817,7 +1794,7 @@ mod tests { assert_matches!( run_hint!(vm, ids_data, hint_code), Err(HintError::OutOfValidRange(bx)) - if *bx == (bound.unwrap(), builtin_bound.field_div(&Felt252::TWO.try_into().unwrap())) + if *bx == (*bound, builtin_bound.field_div(&Felt252::TWO.try_into().unwrap())) ) } diff --git a/vm/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs b/vm/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs index 06d385c1a6..23dc562dae 100644 --- a/vm/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/squash_dict_utils.rs @@ -247,8 +247,7 @@ pub fn squash_dict( let ptr_diff = get_integer_from_var_name("ptr_diff", vm, ids_data, ap_tracking)?; let n_accesses = get_integer_from_var_name("n_accesses", vm, ids_data, ap_tracking)?; //Get range_check_builtin - let range_check_builtin = vm.get_range_check_builtin()?; - let range_check_bound = range_check_builtin._bound; + let range_check_bound = *vm.get_range_check_builtin()?.bound(); //Main Logic let ptr_diff = ptr_diff .to_usize() @@ -284,7 +283,7 @@ pub fn squash_dict( keys.sort(); keys.reverse(); //Are the keys used bigger than the range_check bound. - let big_keys = if keys[0] >= range_check_bound.unwrap() { + let big_keys = if keys[0] >= range_check_bound { Felt252::ONE } else { Felt252::ZERO diff --git a/vm/src/serde/deserialize_program.rs b/vm/src/serde/deserialize_program.rs index a849541d23..b897223f87 100644 --- a/vm/src/serde/deserialize_program.rs +++ b/vm/src/serde/deserialize_program.rs @@ -14,6 +14,7 @@ use crate::{ sync::Arc, }, utils::CAIRO_PRIME, + vm::runners::builtin_runner::RANGE_CHECK_96_BUILTIN_NAME, }; use crate::utils::PRIME_STR; @@ -56,6 +57,7 @@ pub enum BuiltinName { ec_op, poseidon, segment_arena, + range_check96, add_mod, mul_mod, } @@ -72,6 +74,7 @@ impl BuiltinName { BuiltinName::ec_op => EC_OP_BUILTIN_NAME, BuiltinName::poseidon => POSEIDON_BUILTIN_NAME, BuiltinName::segment_arena => SEGMENT_ARENA_BUILTIN_NAME, + BuiltinName::range_check96 => RANGE_CHECK_96_BUILTIN_NAME, BuiltinName::add_mod => ADD_MOD_BUILTIN_NAME, BuiltinName::mul_mod => MUL_MOD_BUILTIN_NAME, } diff --git a/vm/src/types/instance_definitions/builtins_instance_def.rs b/vm/src/types/instance_definitions/builtins_instance_def.rs index 1b21aa6da0..b54cd3c849 100644 --- a/vm/src/types/instance_definitions/builtins_instance_def.rs +++ b/vm/src/types/instance_definitions/builtins_instance_def.rs @@ -18,6 +18,7 @@ pub(crate) struct BuiltinsInstanceDef { pub(crate) ec_op: Option, pub(crate) keccak: Option, pub(crate) poseidon: Option, + pub(crate) range_check96: Option, pub(crate) add_mod: Option, pub(crate) mul_mod: Option, } @@ -33,6 +34,7 @@ impl BuiltinsInstanceDef { ec_op: None, keccak: None, poseidon: None, + range_check96: None, add_mod: None, mul_mod: None, } @@ -48,6 +50,7 @@ impl BuiltinsInstanceDef { ec_op: None, keccak: None, poseidon: None, + range_check96: None, add_mod: None, mul_mod: None, } @@ -63,6 +66,7 @@ impl BuiltinsInstanceDef { ec_op: None, keccak: None, poseidon: None, + range_check96: None, add_mod: None, mul_mod: None, } @@ -78,6 +82,7 @@ impl BuiltinsInstanceDef { ec_op: None, keccak: None, poseidon: None, + range_check96: None, add_mod: None, mul_mod: None, } @@ -87,12 +92,13 @@ impl BuiltinsInstanceDef { BuiltinsInstanceDef { output: true, pedersen: Some(PedersenInstanceDef::new(Some(32), 1)), - range_check: Some(RangeCheckInstanceDef::new(Some(16), 8)), + range_check: Some(RangeCheckInstanceDef::new(Some(16))), ecdsa: Some(EcdsaInstanceDef::new(Some(2048))), bitwise: Some(BitwiseInstanceDef::new(Some(64))), ec_op: Some(EcOpInstanceDef::new(Some(1024))), keccak: None, poseidon: Some(PoseidonInstanceDef::default()), + range_check96: None, add_mod: None, mul_mod: None, } @@ -102,12 +108,13 @@ impl BuiltinsInstanceDef { BuiltinsInstanceDef { output: true, pedersen: Some(PedersenInstanceDef::new(Some(32), 1)), - range_check: Some(RangeCheckInstanceDef::new(Some(16), 8)), + range_check: Some(RangeCheckInstanceDef::new(Some(16))), ecdsa: Some(EcdsaInstanceDef::new(Some(2048))), bitwise: Some(BitwiseInstanceDef::new(Some(64))), ec_op: Some(EcOpInstanceDef::new(Some(1024))), keccak: Some(KeccakInstanceDef::new(Some(2048), vec![200; 8])), poseidon: Some(PoseidonInstanceDef::default()), + range_check96: None, add_mod: None, mul_mod: None, } @@ -123,6 +130,7 @@ impl BuiltinsInstanceDef { ec_op: None, keccak: None, poseidon: Some(PoseidonInstanceDef::new(Some(8))), + range_check96: None, add_mod: None, mul_mod: None, } @@ -138,6 +146,7 @@ impl BuiltinsInstanceDef { ec_op: Some(EcOpInstanceDef::new(Some(1024))), keccak: Some(KeccakInstanceDef::new(Some(2048), vec![200; 8])), poseidon: Some(PoseidonInstanceDef::new(Some(256))), + range_check96: Some(RangeCheckInstanceDef::new(Some(8))), #[cfg(feature = "mod_builtin")] add_mod: Some(ModInstanceDef::new(Some(128), 1, 96)), #[cfg(feature = "mod_builtin")] @@ -159,6 +168,7 @@ impl BuiltinsInstanceDef { ec_op: Some(EcOpInstanceDef::default()), keccak: None, poseidon: None, + range_check96: None, add_mod: None, mul_mod: None, } @@ -168,12 +178,13 @@ impl BuiltinsInstanceDef { BuiltinsInstanceDef { output: true, pedersen: Some(PedersenInstanceDef::new(None, 4)), - range_check: Some(RangeCheckInstanceDef::new(None, 8)), + 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")] 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 ad46df54c6..de9fa51da3 100644 --- a/vm/src/types/instance_definitions/range_check_instance_def.rs +++ b/vm/src/types/instance_definitions/range_check_instance_def.rs @@ -4,27 +4,15 @@ pub(crate) const CELLS_PER_RANGE_CHECK: u32 = 1; #[derive(Serialize, Debug, PartialEq)] pub(crate) struct RangeCheckInstanceDef { pub(crate) ratio: Option, - pub(crate) n_parts: u32, } impl RangeCheckInstanceDef { pub(crate) fn default() -> Self { - RangeCheckInstanceDef { - ratio: Some(8), - n_parts: 8, - } + RangeCheckInstanceDef { ratio: Some(8) } } - pub(crate) fn new(ratio: Option, n_parts: u32) -> Self { - RangeCheckInstanceDef { ratio, n_parts } - } - - pub(crate) fn _cells_per_builtin(&self) -> u32 { - CELLS_PER_RANGE_CHECK - } - - pub(crate) fn _range_check_units_per_builtin(&self) -> u32 { - self.n_parts + pub(crate) fn new(ratio: Option) -> Self { + RangeCheckInstanceDef { ratio } } } @@ -35,37 +23,17 @@ mod tests { #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn get_range_check_units_per_builtin() { - let builtin_instance = RangeCheckInstanceDef::default(); - assert_eq!(builtin_instance._range_check_units_per_builtin(), 8); - } - - #[test] - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] - fn get_cells_per_builtin() { - let builtin_instance = RangeCheckInstanceDef::default(); - assert_eq!(builtin_instance._cells_per_builtin(), 1); - } - #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_new() { - let builtin_instance = RangeCheckInstanceDef { - ratio: Some(10), - n_parts: 10, - }; - assert_eq!(RangeCheckInstanceDef::new(Some(10), 10), builtin_instance); + let builtin_instance = RangeCheckInstanceDef { ratio: Some(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), - n_parts: 8, - }; + let builtin_instance = RangeCheckInstanceDef { ratio: Some(8) }; assert_eq!(RangeCheckInstanceDef::default(), builtin_instance); } } diff --git a/vm/src/utils.rs b/vm/src/utils.rs index 8432a5cd79..4ec902dcfb 100644 --- a/vm/src/utils.rs +++ b/vm/src/utils.rs @@ -236,8 +236,11 @@ pub mod test_utils { () => {{ let mut vm = VirtualMachine::new(false); vm.builtin_runners = vec![ - $crate::vm::runners::builtin_runner::RangeCheckBuiltinRunner::new(Some(8), 8, true) - .into(), + $crate::vm::runners::builtin_runner::RangeCheckBuiltinRunner::<8>::new( + Some(8), + true, + ) + .into(), ]; vm }}; diff --git a/vm/src/vm/runners/builtin_runner/mod.rs b/vm/src/vm/runners/builtin_runner/mod.rs index 9cc2778d11..e8f2e9502e 100644 --- a/vm/src/vm/runners/builtin_runner/mod.rs +++ b/vm/src/vm/runners/builtin_runner/mod.rs @@ -20,6 +20,7 @@ mod range_check; mod segment_arena; mod signature; +pub(crate) use self::range_check::{RC_N_PARTS_96, RC_N_PARTS_STANDARD}; pub use bitwise::BitwiseBuiltinRunner; pub use ec_op::EcOpBuiltinRunner; pub use hash::HashBuiltinRunner; @@ -37,6 +38,7 @@ use super::cairo_pie::BuiltinAdditionalData; pub const OUTPUT_BUILTIN_NAME: &str = "output_builtin"; pub const HASH_BUILTIN_NAME: &str = "pedersen_builtin"; pub const RANGE_CHECK_BUILTIN_NAME: &str = "range_check_builtin"; +pub const RANGE_CHECK_96_BUILTIN_NAME: &str = "range_check_96_builtin"; pub const SIGNATURE_BUILTIN_NAME: &str = "ecdsa_builtin"; pub const BITWISE_BUILTIN_NAME: &str = "bitwise_builtin"; pub const EC_OP_BUILTIN_NAME: &str = "ec_op_builtin"; @@ -60,7 +62,8 @@ pub enum BuiltinRunner { EcOp(EcOpBuiltinRunner), Hash(HashBuiltinRunner), Output(OutputBuiltinRunner), - RangeCheck(RangeCheckBuiltinRunner), + RangeCheck(RangeCheckBuiltinRunner), + RangeCheck96(RangeCheckBuiltinRunner), Keccak(KeccakBuiltinRunner), Signature(SignatureBuiltinRunner), Poseidon(PoseidonBuiltinRunner), @@ -79,6 +82,9 @@ impl BuiltinRunner { BuiltinRunner::RangeCheck(ref mut range_check) => { range_check.initialize_segments(segments) } + BuiltinRunner::RangeCheck96(ref mut range_check) => { + range_check.initialize_segments(segments) + } BuiltinRunner::Keccak(ref mut keccak) => keccak.initialize_segments(segments), BuiltinRunner::Signature(ref mut signature) => signature.initialize_segments(segments), BuiltinRunner::Poseidon(ref mut poseidon) => poseidon.initialize_segments(segments), @@ -96,6 +102,7 @@ impl BuiltinRunner { BuiltinRunner::Hash(ref hash) => hash.initial_stack(), BuiltinRunner::Output(ref output) => output.initial_stack(), BuiltinRunner::RangeCheck(ref range_check) => range_check.initial_stack(), + BuiltinRunner::RangeCheck96(ref range_check) => range_check.initial_stack(), BuiltinRunner::Keccak(ref keccak) => keccak.initial_stack(), BuiltinRunner::Signature(ref signature) => signature.initial_stack(), BuiltinRunner::Poseidon(ref poseidon) => poseidon.initial_stack(), @@ -189,6 +196,7 @@ impl BuiltinRunner { BuiltinRunner::Hash(ref hash) => hash.included, BuiltinRunner::Output(ref output) => output.included, BuiltinRunner::RangeCheck(ref range_check) => range_check.included, + BuiltinRunner::RangeCheck96(ref range_check) => range_check.included, BuiltinRunner::Keccak(ref keccak) => keccak.included, BuiltinRunner::Signature(ref signature) => signature.included, BuiltinRunner::Poseidon(ref poseidon) => poseidon.included, @@ -205,6 +213,7 @@ impl BuiltinRunner { BuiltinRunner::Hash(ref hash) => hash.base(), BuiltinRunner::Output(ref output) => output.base(), BuiltinRunner::RangeCheck(ref range_check) => range_check.base(), + BuiltinRunner::RangeCheck96(ref range_check) => range_check.base(), BuiltinRunner::Keccak(ref keccak) => keccak.base(), BuiltinRunner::Signature(ref signature) => signature.base(), BuiltinRunner::Poseidon(ref poseidon) => poseidon.base(), @@ -221,6 +230,7 @@ impl BuiltinRunner { BuiltinRunner::Hash(hash) => hash.ratio(), BuiltinRunner::Output(_) | BuiltinRunner::SegmentArena(_) => None, BuiltinRunner::RangeCheck(range_check) => range_check.ratio(), + BuiltinRunner::RangeCheck96(range_check) => range_check.ratio(), BuiltinRunner::Keccak(keccak) => keccak.ratio(), BuiltinRunner::Signature(ref signature) => signature.ratio(), BuiltinRunner::Poseidon(poseidon) => poseidon.ratio(), @@ -231,6 +241,7 @@ impl BuiltinRunner { pub fn add_validation_rule(&self, memory: &mut Memory) { match *self { BuiltinRunner::RangeCheck(ref range_check) => range_check.add_validation_rule(memory), + BuiltinRunner::RangeCheck96(ref range_check) => range_check.add_validation_rule(memory), BuiltinRunner::Signature(ref signature) => signature.add_validation_rule(memory), BuiltinRunner::Poseidon(ref poseidon) => poseidon.add_validation_rule(memory), _ => {} @@ -263,6 +274,7 @@ impl BuiltinRunner { BuiltinRunner::Hash(ref hash) => hash.get_used_cells(segments), BuiltinRunner::Output(ref output) => output.get_used_cells(segments), BuiltinRunner::RangeCheck(ref range_check) => range_check.get_used_cells(segments), + BuiltinRunner::RangeCheck96(ref range_check) => range_check.get_used_cells(segments), BuiltinRunner::Keccak(ref keccak) => keccak.get_used_cells(segments), BuiltinRunner::Signature(ref signature) => signature.get_used_cells(segments), BuiltinRunner::Poseidon(ref poseidon) => poseidon.get_used_cells(segments), @@ -283,6 +295,9 @@ impl BuiltinRunner { BuiltinRunner::Hash(ref hash) => hash.get_used_instances(segments), BuiltinRunner::Output(ref output) => output.get_used_instances(segments), BuiltinRunner::RangeCheck(ref range_check) => range_check.get_used_instances(segments), + BuiltinRunner::RangeCheck96(ref range_check) => { + range_check.get_used_instances(segments) + } BuiltinRunner::Keccak(ref keccak) => keccak.get_used_instances(segments), BuiltinRunner::Signature(ref signature) => signature.get_used_instances(segments), BuiltinRunner::Poseidon(ref poseidon) => poseidon.get_used_instances(segments), @@ -296,6 +311,9 @@ impl BuiltinRunner { pub fn get_range_check_usage(&self, memory: &Memory) -> Option<(usize, usize)> { match self { BuiltinRunner::RangeCheck(ref range_check) => range_check.get_range_check_usage(memory), + BuiltinRunner::RangeCheck96(ref range_check) => { + range_check.get_range_check_usage(memory) + } _ => None, } } @@ -308,7 +326,11 @@ impl BuiltinRunner { match self { BuiltinRunner::RangeCheck(range_check) => { let (used_cells, _) = self.get_used_cells_and_allocated_size(vm)?; - Ok(used_cells * range_check.n_parts as usize) + Ok(used_cells * range_check.n_parts() as usize) + } + BuiltinRunner::RangeCheck96(range_check) => { + let (used_cells, _) = self.get_used_cells_and_allocated_size(vm)?; + Ok(used_cells * range_check.n_parts() as usize) } _ => Ok(0), } @@ -332,6 +354,7 @@ impl BuiltinRunner { BuiltinRunner::EcOp(builtin) => builtin.cells_per_instance, BuiltinRunner::Hash(builtin) => builtin.cells_per_instance, BuiltinRunner::RangeCheck(builtin) => builtin.cells_per_instance, + BuiltinRunner::RangeCheck96(builtin) => builtin.cells_per_instance, BuiltinRunner::Output(_) => 0, BuiltinRunner::Keccak(builtin) => builtin.cells_per_instance, BuiltinRunner::Signature(builtin) => builtin.cells_per_instance, @@ -347,6 +370,7 @@ impl BuiltinRunner { BuiltinRunner::EcOp(builtin) => builtin.n_input_cells, BuiltinRunner::Hash(builtin) => builtin.n_input_cells, BuiltinRunner::RangeCheck(builtin) => builtin.n_input_cells, + BuiltinRunner::RangeCheck96(builtin) => builtin.n_input_cells, BuiltinRunner::Output(_) => 0, BuiltinRunner::Keccak(builtin) => builtin.n_input_cells, BuiltinRunner::Signature(builtin) => builtin.n_input_cells, @@ -362,6 +386,7 @@ impl BuiltinRunner { BuiltinRunner::EcOp(builtin) => builtin.instances_per_component, BuiltinRunner::Hash(builtin) => builtin.instances_per_component, BuiltinRunner::RangeCheck(builtin) => builtin.instances_per_component, + BuiltinRunner::RangeCheck96(builtin) => builtin.instances_per_component, BuiltinRunner::Output(_) | BuiltinRunner::SegmentArena(_) => 1, BuiltinRunner::Keccak(builtin) => builtin.instances_per_component, BuiltinRunner::Signature(builtin) => builtin.instances_per_component, @@ -377,6 +402,7 @@ impl BuiltinRunner { BuiltinRunner::EcOp(_) => EC_OP_BUILTIN_NAME, BuiltinRunner::Hash(_) => HASH_BUILTIN_NAME, BuiltinRunner::RangeCheck(_) => RANGE_CHECK_BUILTIN_NAME, + BuiltinRunner::RangeCheck96(_) => RANGE_CHECK_96_BUILTIN_NAME, BuiltinRunner::Output(_) => OUTPUT_BUILTIN_NAME, BuiltinRunner::Keccak(_) => KECCAK_BUILTIN_NAME, BuiltinRunner::Signature(_) => SIGNATURE_BUILTIN_NAME, @@ -489,6 +515,7 @@ impl BuiltinRunner { pub fn air_private_input(&self, segments: &MemorySegmentManager) -> Vec { match self { BuiltinRunner::RangeCheck(builtin) => builtin.air_private_input(&segments.memory), + BuiltinRunner::RangeCheck96(builtin) => builtin.air_private_input(&segments.memory), BuiltinRunner::Bitwise(builtin) => builtin.air_private_input(&segments.memory), BuiltinRunner::Hash(builtin) => builtin.air_private_input(&segments.memory), BuiltinRunner::EcOp(builtin) => builtin.air_private_input(&segments.memory), @@ -507,6 +534,9 @@ impl BuiltinRunner { BuiltinRunner::Hash(ref mut hash) => hash.stop_ptr = Some(stop_ptr), BuiltinRunner::Output(ref mut output) => output.stop_ptr = Some(stop_ptr), BuiltinRunner::RangeCheck(ref mut range_check) => range_check.stop_ptr = Some(stop_ptr), + BuiltinRunner::RangeCheck96(ref mut range_check) => { + range_check.stop_ptr = Some(stop_ptr) + } BuiltinRunner::Keccak(ref mut keccak) => keccak.stop_ptr = Some(stop_ptr), BuiltinRunner::Signature(ref mut signature) => signature.stop_ptr = Some(stop_ptr), BuiltinRunner::Poseidon(ref mut poseidon) => poseidon.stop_ptr = Some(stop_ptr), @@ -524,6 +554,7 @@ impl BuiltinRunner { BuiltinRunner::Hash(ref hash) => hash.stop_ptr, BuiltinRunner::Output(ref output) => output.stop_ptr, BuiltinRunner::RangeCheck(ref range_check) => range_check.stop_ptr, + BuiltinRunner::RangeCheck96(ref range_check) => range_check.stop_ptr, BuiltinRunner::Keccak(ref keccak) => keccak.stop_ptr, BuiltinRunner::Signature(ref signature) => signature.stop_ptr, BuiltinRunner::Poseidon(ref poseidon) => poseidon.stop_ptr, @@ -563,12 +594,18 @@ impl From for BuiltinRunner { } } -impl From for BuiltinRunner { - fn from(runner: RangeCheckBuiltinRunner) -> Self { +impl From> for BuiltinRunner { + fn from(runner: RangeCheckBuiltinRunner) -> Self { BuiltinRunner::RangeCheck(runner) } } +impl From> for BuiltinRunner { + fn from(runner: RangeCheckBuiltinRunner) -> Self { + BuiltinRunner::RangeCheck96(runner) + } +} + impl From for BuiltinRunner { fn from(runner: SignatureBuiltinRunner) -> Self { BuiltinRunner::Signature(runner) @@ -635,7 +672,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_n_input_cells_range_check() { - let range_check = RangeCheckBuiltinRunner::new(Some(10), 10, true); + let range_check = RangeCheckBuiltinRunner::::new(Some(10), true); let builtin: BuiltinRunner = range_check.clone().into(); assert_eq!(range_check.n_input_cells, builtin.n_input_cells()) } @@ -683,7 +720,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_cells_per_instance_range_check() { - let range_check = RangeCheckBuiltinRunner::new(Some(10), 10, true); + let range_check = RangeCheckBuiltinRunner::::new(Some(10), true); let builtin: BuiltinRunner = range_check.clone().into(); assert_eq!(range_check.cells_per_instance, builtin.cells_per_instance()) } @@ -739,7 +776,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_name_range_check() { - let range_check = RangeCheckBuiltinRunner::new(Some(10), 10, true); + let range_check = RangeCheckBuiltinRunner::::new(Some(10), true); let builtin: BuiltinRunner = range_check.into(); assert_eq!(RANGE_CHECK_BUILTIN_NAME, builtin.name()) } @@ -909,7 +946,9 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_allocated_memory_units_range_check_with_items() { - let builtin = BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(10), 12, true)); + let builtin = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(10), true), + ); let mut vm = vm!(); @@ -996,7 +1035,9 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_allocated_memory_units_range_check() { - let builtin = BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(8), 8, true)); + let builtin = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(8), true), + ); let mut vm = vm!(); vm.current_step = 8; assert_eq!(builtin.get_allocated_memory_units(&vm), Ok(1)); @@ -1048,7 +1089,9 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_range_check_usage_range_check() { - let builtin = BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(8), 8, true)); + let builtin = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(8), true), + ); let memory = memory![((0, 0), 1), ((0, 1), 2), ((0, 2), 3), ((0, 3), 4)]; assert_eq!(builtin.get_range_check_usage(&memory), Some((0, 4))); } @@ -1139,7 +1182,9 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_used_diluted_check_units_range_check() { - let builtin = BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(8), 8, true)); + let builtin = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(8), true), + ); assert_eq!(builtin.get_used_diluted_check_units(270, 7), 0); } @@ -1163,8 +1208,9 @@ mod tests { assert_eq!(hash_builtin.get_memory_segment_addresses(), (0, None),); let output_builtin: BuiltinRunner = OutputBuiltinRunner::new(true).into(); assert_eq!(output_builtin.get_memory_segment_addresses(), (0, None),); - let range_check_builtin: BuiltinRunner = - BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(8), 8, true)); + let range_check_builtin: BuiltinRunner = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(8), true), + ); assert_eq!( range_check_builtin.get_memory_segment_addresses(), (0, None), @@ -1300,7 +1346,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_security_checks_range_check_missing_memory_cells_with_offsets() { - let range_check_builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let range_check_builtin = + RangeCheckBuiltinRunner::::new(Some(8), true); let builtin: BuiltinRunner = range_check_builtin.into(); let mut vm = vm!(); @@ -1324,8 +1371,9 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_security_checks_range_check_missing_memory_cells() { - let builtin: BuiltinRunner = - BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(8), 8, true)); + let builtin: BuiltinRunner = BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::< + RC_N_PARTS_STANDARD, + >::new(Some(8), true)); let mut vm = vm!(); vm.segments.memory = memory![((0, 1), 1)]; @@ -1341,7 +1389,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_security_checks_range_check_empty() { - let range_check_builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let range_check_builtin = + RangeCheckBuiltinRunner::::new(Some(8), true); let builtin: BuiltinRunner = range_check_builtin.into(); @@ -1539,7 +1588,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_used_perm_range_check_units_range_check() { - let builtin_runner: BuiltinRunner = RangeCheckBuiltinRunner::new(Some(8), 8, true).into(); + let builtin_runner: BuiltinRunner = + RangeCheckBuiltinRunner::::new(Some(8), true).into(); let mut vm = vm!(); vm.current_step = 8; @@ -1560,8 +1610,9 @@ mod tests { assert_eq!(hash_builtin.ratio(), (Some(8)),); let output_builtin: BuiltinRunner = OutputBuiltinRunner::new(true).into(); assert_eq!(output_builtin.ratio(), None,); - let range_check_builtin: BuiltinRunner = - BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(8), 8, true)); + let range_check_builtin: BuiltinRunner = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(8), true), + ); assert_eq!(range_check_builtin.ratio(), (Some(8)),); let keccak_builtin: BuiltinRunner = KeccakBuiltinRunner::new(&KeccakInstanceDef::default(), true).into(); @@ -1615,8 +1666,9 @@ mod tests { let mut vm = vm!(); vm.segments.segment_used_sizes = Some(vec![4]); - let range_check_builtin: BuiltinRunner = - BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(8), 8, true)); + let range_check_builtin: BuiltinRunner = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(8), true), + ); assert_eq!(range_check_builtin.get_used_instances(&vm.segments), Ok(4)); } @@ -1631,7 +1683,10 @@ mod tests { BuiltinRunner::EcOp(EcOpBuiltinRunner::new(&EcOpInstanceDef::default(), false)), BuiltinRunner::Hash(HashBuiltinRunner::new(Some(1), false)), BuiltinRunner::Output(OutputBuiltinRunner::new(false)), - BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(8), 8, false)), + BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::::new( + Some(8), + false, + )), BuiltinRunner::Keccak(KeccakBuiltinRunner::new( &KeccakInstanceDef::default(), false, @@ -1659,7 +1714,10 @@ mod tests { BuiltinRunner::EcOp(EcOpBuiltinRunner::new(&EcOpInstanceDef::default(), false)), BuiltinRunner::Hash(HashBuiltinRunner::new(Some(1), false)), BuiltinRunner::Output(OutputBuiltinRunner::new(false)), - BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(8), 8, false)), + BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::::new( + Some(8), + false, + )), BuiltinRunner::Keccak(KeccakBuiltinRunner::new( &KeccakInstanceDef::default(), false, diff --git a/vm/src/vm/runners/builtin_runner/modulo.rs b/vm/src/vm/runners/builtin_runner/modulo.rs index 8e74113096..dc4e69f8c1 100644 --- a/vm/src/vm/runners/builtin_runner/modulo.rs +++ b/vm/src/vm/runners/builtin_runner/modulo.rs @@ -739,8 +739,8 @@ mod tests { p1: Felt252::ONE, p2: Felt252::ZERO, p3: Felt252::ZERO, - values_ptr: 18927, - offsets_ptr: 18959, + values_ptr: 23023, + offsets_ptr: 23055, n: 2, batch: BTreeMap::from([( 0, @@ -769,8 +769,8 @@ mod tests { p1: Felt252::ONE, p2: Felt252::ZERO, p3: Felt252::ZERO, - values_ptr: 18927, - offsets_ptr: 18962, + values_ptr: 23023, + offsets_ptr: 23058, n: 1, batch: BTreeMap::from([( 0, @@ -794,7 +794,7 @@ mod tests { ),]) } ], - zero_value_address: 18027 + zero_value_address: 22123 }) ); assert_eq!( @@ -807,8 +807,8 @@ mod tests { p1: Felt252::ONE, p2: Felt252::ZERO, p3: Felt252::ZERO, - values_ptr: 18927, - offsets_ptr: 18965, + values_ptr: 23023, + offsets_ptr: 23061, n: 3, batch: BTreeMap::from([( 0, @@ -837,8 +837,8 @@ mod tests { p1: Felt252::ONE, p2: Felt252::ZERO, p3: Felt252::ZERO, - values_ptr: 18927, - offsets_ptr: 18968, + values_ptr: 23023, + offsets_ptr: 23064, n: 2, batch: BTreeMap::from([( 0, @@ -867,8 +867,8 @@ mod tests { p1: Felt252::ONE, p2: Felt252::ZERO, p3: Felt252::ZERO, - values_ptr: 18927, - offsets_ptr: 18971, + values_ptr: 23023, + offsets_ptr: 23067, n: 1, batch: BTreeMap::from([( 0, @@ -892,7 +892,7 @@ mod tests { ),]) } ], - zero_value_address: 18027 + zero_value_address: 22123 }) ) } diff --git a/vm/src/vm/runners/builtin_runner/range_check.rs b/vm/src/vm/runners/builtin_runner/range_check.rs index 64d045f4e1..cb02e79b46 100644 --- a/vm/src/vm/runners/builtin_runner/range_check.rs +++ b/vm/src/vm/runners/builtin_runner/range_check.rs @@ -21,47 +21,42 @@ use crate::{ }, }; -use num_traits::Zero; +use lazy_static::lazy_static; + +use super::{RANGE_CHECK_96_BUILTIN_NAME, RANGE_CHECK_BUILTIN_NAME}; -// NOTE: the current implementation is based on the bound 0x10000 -const _INNER_RC_BOUND: u64 = 1u64 << INNER_RC_BOUND_SHIFT; const INNER_RC_BOUND_SHIFT: u64 = 16; const INNER_RC_BOUND_MASK: u64 = u16::MAX as u64; -// TODO: use constant instead of receiving as false parameter -const N_PARTS: u64 = 8; +pub const RC_N_PARTS_STANDARD: u64 = 8; +pub const RC_N_PARTS_96: u64 = 6; + +lazy_static! { + pub static ref BOUND_STANDARD: Felt252 = + Felt252::TWO.pow(INNER_RC_BOUND_SHIFT * RC_N_PARTS_STANDARD); + pub static ref BOUND_96: Felt252 = Felt252::TWO.pow(INNER_RC_BOUND_SHIFT * RC_N_PARTS_96); +} #[derive(Debug, Clone)] -pub struct RangeCheckBuiltinRunner { +pub struct RangeCheckBuiltinRunner { ratio: Option, base: usize, pub(crate) stop_ptr: Option, pub(crate) cells_per_instance: u32, pub(crate) n_input_cells: u32, - pub _bound: Option, pub(crate) included: bool, - pub(crate) n_parts: u32, pub(crate) instances_per_component: u32, } -impl RangeCheckBuiltinRunner { - pub fn new(ratio: Option, n_parts: u32, included: bool) -> RangeCheckBuiltinRunner { - let bound = Felt252::TWO.pow(16 * n_parts as u128); - let _bound = if n_parts != 0 && bound.is_zero() { - None - } else { - Some(bound) - }; - +impl RangeCheckBuiltinRunner { + pub fn new(ratio: Option, included: bool) -> RangeCheckBuiltinRunner { RangeCheckBuiltinRunner { ratio, base: 0, stop_ptr: None, cells_per_instance: CELLS_PER_RANGE_CHECK, n_input_cells: CELLS_PER_RANGE_CHECK, - _bound, included, - n_parts, instances_per_component: 1, } } @@ -86,8 +81,26 @@ impl RangeCheckBuiltinRunner { self.ratio } + pub fn name(&self) -> &'static str { + match N_PARTS { + RC_N_PARTS_96 => RANGE_CHECK_96_BUILTIN_NAME, + _ => RANGE_CHECK_BUILTIN_NAME, + } + } + + pub fn n_parts(&self) -> u64 { + N_PARTS + } + + pub fn bound(&self) -> &'static Felt252 { + match N_PARTS { + RC_N_PARTS_96 => &BOUND_96, + _ => &BOUND_STANDARD, + } + } + pub fn add_validation_rule(&self, memory: &mut Memory) { - let rule: ValidationRule = ValidationRule(Box::new( + let rule = ValidationRule(Box::new( |memory: &Memory, address: Relocatable| -> Result, MemoryError> { let num = memory .get_integer(address) @@ -130,7 +143,7 @@ impl RangeCheckBuiltinRunner { .rev() .map(move |i| ((digit >> (i * INNER_RC_BOUND_SHIFT)) & INNER_RC_BOUND_MASK)) }) - .take(self.n_parts as usize) + .take(N_PARTS as usize) .fold(rc_bounds, |mm, x| { (min(mm.0, x as usize), max(mm.1, x as usize)) }); @@ -182,7 +195,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_used_instances() { - let builtin = RangeCheckBuiltinRunner::new(Some(10), 12, true); + let builtin = RangeCheckBuiltinRunner::::new(Some(10), true); let mut vm = vm!(); vm.segments.segment_used_sizes = Some(vec![1]); @@ -193,7 +206,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn final_stack() { - let mut builtin: BuiltinRunner = RangeCheckBuiltinRunner::new(Some(10), 12, true).into(); + let mut builtin: BuiltinRunner = + RangeCheckBuiltinRunner::::new(Some(10), true).into(); let mut vm = vm!(); @@ -217,7 +231,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn final_stack_error_stop_pointer() { - let mut builtin: BuiltinRunner = RangeCheckBuiltinRunner::new(Some(10), 12, true).into(); + let mut builtin: BuiltinRunner = + RangeCheckBuiltinRunner::::new(Some(10), true).into(); let mut vm = vm!(); @@ -245,7 +260,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn final_stack_error_when_notincluded() { - let mut builtin: BuiltinRunner = RangeCheckBuiltinRunner::new(Some(10), 12, false).into(); + let mut builtin: BuiltinRunner = + RangeCheckBuiltinRunner::::new(Some(10), false).into(); let mut vm = vm!(); @@ -269,7 +285,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn final_stack_error_non_relocatable() { - let mut builtin: BuiltinRunner = RangeCheckBuiltinRunner::new(Some(10), 12, true).into(); + let mut builtin: BuiltinRunner = + RangeCheckBuiltinRunner::::new(Some(10), true).into(); let mut vm = vm!(); @@ -295,7 +312,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_used_cells_and_allocated_size_test() { - let builtin: BuiltinRunner = RangeCheckBuiltinRunner::new(Some(10), 12, true).into(); + let builtin: BuiltinRunner = + RangeCheckBuiltinRunner::::new(Some(10), true).into(); let mut vm = vm!(); @@ -341,7 +359,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_allocated_memory_units() { - let builtin: BuiltinRunner = RangeCheckBuiltinRunner::new(Some(10), 12, true).into(); + let builtin: BuiltinRunner = + RangeCheckBuiltinRunner::::new(Some(10), true).into(); let mut vm = vm!(); @@ -385,7 +404,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn initialize_segments_for_range_check() { - let mut builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let mut builtin = RangeCheckBuiltinRunner::::new(Some(8), true); let mut segments = MemorySegmentManager::new(); builtin.initialize_segments(&mut segments); assert_eq!(builtin.base, 0); @@ -394,7 +413,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_initial_stack_for_range_check_with_base() { - let mut builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let mut builtin = RangeCheckBuiltinRunner::::new(Some(8), true); builtin.base = 1; let initial_stack = builtin.initial_stack(); assert_eq!( @@ -407,21 +426,23 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_base() { - let builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let builtin = RangeCheckBuiltinRunner::::new(Some(8), true); assert_eq!(builtin.base(), 0); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn test_ratio() { - let builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let builtin = RangeCheckBuiltinRunner::::new(Some(8), true); assert_eq!(builtin.ratio(), Some(8)); } #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_used_cells_missing_segment_used_sizes() { - let builtin = BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(256), 8, true)); + let builtin = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(256), true), + ); let vm = vm!(); assert_eq!( @@ -433,7 +454,9 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_used_cells_empty() { - let builtin = BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(256), 8, true)); + let builtin = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(256), true), + ); let mut vm = vm!(); vm.segments.segment_used_sizes = Some(vec![0]); @@ -443,7 +466,9 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_used_cells() { - let builtin = BuiltinRunner::RangeCheck(RangeCheckBuiltinRunner::new(Some(256), 8, true)); + let builtin = BuiltinRunner::RangeCheck( + RangeCheckBuiltinRunner::::new(Some(256), true), + ); let mut vm = vm!(); vm.segments.segment_used_sizes = Some(vec![4]); @@ -453,7 +478,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_range_check_usage_succesful_a() { - let builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let builtin = RangeCheckBuiltinRunner::::new(Some(8), true); let memory = memory![((0, 0), 1), ((0, 1), 2), ((0, 2), 3), ((0, 3), 4)]; assert_eq!(builtin.get_range_check_usage(&memory), Some((0, 4))); } @@ -461,7 +486,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_range_check_usage_succesful_b() { - let builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let builtin = RangeCheckBuiltinRunner::::new(Some(8), true); let memory = memory![ ((0, 0), 1465218365), ((0, 1), 2134570341), @@ -474,7 +499,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_range_check_usage_succesful_c() { - let builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let builtin = RangeCheckBuiltinRunner::::new(Some(8), true); let memory = memory![ ((0, 0), 634834751465218365_i64), ((0, 1), 42876922134570341_i64), @@ -489,7 +514,7 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_range_check_empty_memory() { - let builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let builtin = RangeCheckBuiltinRunner::::new(Some(8), true); let memory = Memory::new(); assert_eq!(builtin.get_range_check_usage(&memory), None); } @@ -498,7 +523,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_used_perm_range_check_units() { - let builtin_runner: BuiltinRunner = RangeCheckBuiltinRunner::new(Some(8), 8, true).into(); + let builtin_runner: BuiltinRunner = + RangeCheckBuiltinRunner::::new(Some(8), true).into(); let mut vm = vm!(); vm.current_step = 8; @@ -509,7 +535,8 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn get_air_private_input() { - let builtin: BuiltinRunner = RangeCheckBuiltinRunner::new(None, 4, true).into(); + let builtin: BuiltinRunner = + RangeCheckBuiltinRunner::::new(None, true).into(); let segments = segments![((0, 0), 0), ((0, 1), 1), ((0, 2), 2)]; assert_eq!( diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index f0482d4724..914f0e32c5 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -56,7 +56,9 @@ use serde::{Deserialize, Serialize}; use super::builtin_runner::ModBuiltinRunner; use super::{ - builtin_runner::{KeccakBuiltinRunner, PoseidonBuiltinRunner}, + builtin_runner::{ + KeccakBuiltinRunner, PoseidonBuiltinRunner, RC_N_PARTS_96, RC_N_PARTS_STANDARD, + }, cairo_pie::{self, CairoPie, CairoPieMetadata, CairoPieVersion}, }; use crate::types::instance_definitions::mod_instance_def::ModInstanceDef; @@ -261,6 +263,7 @@ impl CairoRunner { BuiltinName::ec_op, BuiltinName::keccak, BuiltinName::poseidon, + BuiltinName::range_check96, BuiltinName::add_mod, BuiltinName::mul_mod, ]; @@ -288,9 +291,8 @@ impl CairoRunner { let included = program_builtins.remove(&BuiltinName::range_check); if included || self.is_proof_mode() { builtin_runners.push( - RangeCheckBuiltinRunner::new( + RangeCheckBuiltinRunner::::new( instance_def.ratio, - instance_def.n_parts, included, ) .into(), @@ -333,6 +335,16 @@ impl CairoRunner { .push(PoseidonBuiltinRunner::new(instance_def.ratio, included).into()); } } + + if let Some(instance_def) = self.layout.builtins.range_check96.as_ref() { + let included = program_builtins.remove(&BuiltinName::range_check96); + if included || self.is_proof_mode() { + builtin_runners.push( + RangeCheckBuiltinRunner::::new(instance_def.ratio, included) + .into(), + ); + } + } if let Some(instance_def) = self.layout.builtins.add_mod.as_ref() { let included = program_builtins.remove(&BuiltinName::add_mod); if included || self.is_proof_mode() { @@ -388,9 +400,9 @@ impl CairoRunner { BuiltinName::pedersen => vm .builtin_runners .push(HashBuiltinRunner::new(Some(32), true).into()), - BuiltinName::range_check => vm - .builtin_runners - .push(RangeCheckBuiltinRunner::new(Some(1), 8, true).into()), + BuiltinName::range_check => vm.builtin_runners.push( + RangeCheckBuiltinRunner::::new(Some(1), true).into(), + ), BuiltinName::output => vm .builtin_runners .push(OutputBuiltinRunner::new(true).into()), @@ -416,6 +428,9 @@ impl CairoRunner { .push(SegmentArenaBuiltinRunner::new(true).into()) } } + BuiltinName::range_check96 => vm + .builtin_runners + .push(RangeCheckBuiltinRunner::::new(Some(1), true).into()), BuiltinName::add_mod => vm.builtin_runners.push( ModBuiltinRunner::new_add_mod(&ModInstanceDef::new(Some(1), 1, 96), true) .into(), @@ -4097,7 +4112,8 @@ mod tests { vm.segments.memory.data = vec![vec![Some(MemoryCell::new(mayberelocatable!( 0x80FF_8000_0530u64 )))]]; - vm.builtin_runners = vec![RangeCheckBuiltinRunner::new(Some(12), 5, true).into()]; + vm.builtin_runners = + vec![RangeCheckBuiltinRunner::::new(Some(12), true).into()]; assert_matches!( cairo_runner.get_perm_range_check_limits(&vm), @@ -4151,7 +4167,8 @@ mod tests { let cairo_runner = cairo_runner!(program); let mut vm = vm!(); - vm.builtin_runners = vec![RangeCheckBuiltinRunner::new(Some(8), 8, true).into()]; + vm.builtin_runners = + vec![RangeCheckBuiltinRunner::::new(Some(8), true).into()]; vm.segments.memory.data = vec![vec![Some(MemoryCell::new(mayberelocatable!( 0x80FF_8000_0530u64 )))]]; @@ -4218,7 +4235,8 @@ mod tests { let cairo_runner = cairo_runner!(program); let mut vm = vm!(); - vm.builtin_runners = vec![RangeCheckBuiltinRunner::new(Some(8), 8, true).into()]; + vm.builtin_runners = + vec![RangeCheckBuiltinRunner::::new(Some(8), true).into()]; vm.segments.memory.data = vec![vec![Some(MemoryCell::new(mayberelocatable!( 0x80FF_8000_0530u64 )))]]; diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index afbf384ddf..dc8818e81d 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -36,6 +36,7 @@ use num_traits::{ToPrimitive, Zero}; use super::errors::runner_errors::RunnerError; use super::runners::builtin_runner::{ ModBuiltinRunner, ADD_MOD_BUILTIN_NAME, MUL_MOD_BUILTIN_NAME, OUTPUT_BUILTIN_NAME, + RC_N_PARTS_STANDARD, }; const MAX_TRACEBACK_ENTRIES: u32 = 20; @@ -926,7 +927,9 @@ impl VirtualMachine { self.segments.memory.get_integer_range(addr, size) } - pub fn get_range_check_builtin(&self) -> Result<&RangeCheckBuiltinRunner, VirtualMachineError> { + pub fn get_range_check_builtin( + &self, + ) -> Result<&RangeCheckBuiltinRunner, VirtualMachineError> { for builtin in &self.builtin_runners { if let BuiltinRunner::RangeCheck(range_check_builtin) = builtin { return Ok(range_check_builtin); diff --git a/vm/src/vm/vm_memory/memory.rs b/vm/src/vm/vm_memory/memory.rs index 178387f504..c776fa14d3 100644 --- a/vm/src/vm/vm_memory/memory.rs +++ b/vm/src/vm/vm_memory/memory.rs @@ -632,7 +632,9 @@ mod memory_tests { types::instance_definitions::ecdsa_instance_def::EcdsaInstanceDef, utils::test_utils::*, vm::{ - runners::builtin_runner::{RangeCheckBuiltinRunner, SignatureBuiltinRunner}, + runners::builtin_runner::{ + RangeCheckBuiltinRunner, SignatureBuiltinRunner, RC_N_PARTS_STANDARD, + }, vm_memory::memory_segments::MemorySegmentManager, }, }; @@ -803,7 +805,7 @@ mod memory_tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn validate_existing_memory_for_range_check_within_bounds() { - let mut builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let mut builtin = RangeCheckBuiltinRunner::::new(Some(8), true); let mut segments = MemorySegmentManager::new(); builtin.initialize_segments(&mut segments); builtin.add_validation_rule(&mut segments.memory); @@ -828,7 +830,7 @@ mod memory_tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn validate_existing_memory_for_range_check_outside_bounds() { - let mut builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let mut builtin = RangeCheckBuiltinRunner::::new(Some(8), true); let mut segments = MemorySegmentManager::new(); segments.add(); builtin.initialize_segments(&mut segments); @@ -919,7 +921,7 @@ mod memory_tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn validate_existing_memory_for_range_check_relocatable_value() { - let mut builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let mut builtin = RangeCheckBuiltinRunner::::new(Some(8), true); let mut segments = MemorySegmentManager::new(); builtin.initialize_segments(&mut segments); segments.memory = memory![((0, 0), (0, 4))]; @@ -936,7 +938,7 @@ mod memory_tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn validate_existing_memory_for_range_check_out_of_bounds_diff_segment() { - let mut builtin = RangeCheckBuiltinRunner::new(Some(8), 8, true); + let mut builtin = RangeCheckBuiltinRunner::::new(Some(8), true); let mut segments = MemorySegmentManager::new(); segments.memory = Memory::new(); segments.add();