Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: Reorganized builtins to be in the top of stack at the end of a run (Cairo1).

* BREAKING: Remove `CairoRunner::add_additional_hash_builtin` & `VirtualMachine::disable_trace`[#1658](https://github.com/lambdaclass/cairo-vm/pull/1658)
Expand Down
75 changes: 25 additions & 50 deletions vm/src/hint_processor/builtin_hint_processor/math_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
%{
Expand Down Expand Up @@ -184,9 +174,9 @@ pub fn assert_le_felt_v_0_8(
b.clone().into_owned(),
))));
}
let bound = vm.get_range_check_builtin()?._bound.unwrap_or_default();
let bound = vm.get_range_check_builtin()?.bound();
let small_inputs =
Felt252::from((a.as_ref() < &bound && b.as_ref() - a.as_ref() < bound) as u8);
Felt252::from((a.as_ref() < bound && b.as_ref() - a.as_ref() < *bound) as u8);
insert_value_from_var_name("small_inputs", small_inputs, vm, ids_data, ap_tracking)
}

Expand Down Expand Up @@ -299,11 +289,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.into_owned())))
}
_ => Ok(()),
if a.as_ref() >= range_check_builtin.bound() {
Err(HintError::AssertNNValueOutOfRange(Box::new(a.into_owned())))
} else {
Ok(())
}
}

Expand Down Expand Up @@ -381,14 +370,11 @@ 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.into_owned(),
)))
}
_ => {}
};
if abs_value >= range_check_builtin.bound().to_biguint() {
return Err(HintError::ValueOutsideValidRange(Box::new(
value.into_owned(),
)));
}

let result = Felt252::from((sign == Sign::Plus) as u8);
insert_value_from_var_name("is_positive", result, vm, ids_data, ap_tracking)
Expand Down Expand Up @@ -474,7 +460,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.into_owned(),
Expand Down Expand Up @@ -528,25 +514,14 @@ 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.into_owned(),
*builtin_bound,
))));
}
None if div.is_zero() => {
return Err(HintError::OutOfValidRange(Box::new((
div.into_owned(),
Felt252::ZERO - Felt252::ONE,
))));
}
_ => {}
if div.is_zero() || div.as_ref() > &div_prime_by_bound(*builtin_bound)? {
return Err(HintError::OutOfValidRange(Box::new((
div.into_owned(),
*builtin_bound,
))));
}

let (q, r) = value.div_rem(&(*div).try_into().map_err(|_| MathError::DividedByZero)?);
Expand Down Expand Up @@ -1830,17 +1805,17 @@ 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
let builtin_bound = felt_str!("340282366920938463463374607431768211456");
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()))
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -285,7 +284,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
Expand Down
3 changes: 3 additions & 0 deletions vm/src/serde/deserialize_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -55,6 +56,7 @@ pub enum BuiltinName {
ec_op,
poseidon,
segment_arena,
range_check96,
}

impl BuiltinName {
Expand All @@ -69,6 +71,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,
}
}
}
Expand Down
17 changes: 14 additions & 3 deletions vm/src/types/instance_definitions/builtins_instance_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub(crate) struct BuiltinsInstanceDef {
pub(crate) ec_op: Option<EcOpInstanceDef>,
pub(crate) keccak: Option<KeccakInstanceDef>,
pub(crate) poseidon: Option<PoseidonInstanceDef>,
pub(crate) range_check96: Option<RangeCheckInstanceDef>,
}

impl BuiltinsInstanceDef {
Expand All @@ -29,6 +30,7 @@ impl BuiltinsInstanceDef {
ec_op: None,
keccak: None,
poseidon: None,
range_check96: None,
}
}

Expand All @@ -42,6 +44,7 @@ impl BuiltinsInstanceDef {
ec_op: None,
keccak: None,
poseidon: None,
range_check96: None,
}
}

Expand All @@ -55,6 +58,7 @@ impl BuiltinsInstanceDef {
ec_op: None,
keccak: None,
poseidon: None,
range_check96: None,
}
}

Expand All @@ -68,32 +72,35 @@ impl BuiltinsInstanceDef {
ec_op: None,
keccak: None,
poseidon: None,
range_check96: None,
}
}

pub(crate) fn starknet() -> 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,
}
}

pub(crate) fn starknet_with_keccak() -> 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,
}
}

Expand All @@ -107,6 +114,7 @@ impl BuiltinsInstanceDef {
ec_op: None,
keccak: None,
poseidon: Some(PoseidonInstanceDef::new(Some(8))),
range_check96: None,
}
}

Expand All @@ -120,6 +128,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))),
}
}

Expand All @@ -133,19 +142,21 @@ impl BuiltinsInstanceDef {
ec_op: Some(EcOpInstanceDef::default()),
keccak: None,
poseidon: None,
range_check96: None,
}
}

pub(crate) fn dynamic() -> 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,
}
}
}
Expand Down
44 changes: 6 additions & 38 deletions vm/src/types/instance_definitions/range_check_instance_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u32>,
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<u32>, 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<u32>) -> Self {
RangeCheckInstanceDef { ratio }
}
}

Expand All @@ -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);
}
}
7 changes: 5 additions & 2 deletions vm/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}};
Expand Down
Loading