Skip to content

Commit

Permalink
Add support for subtractions contenting references as right hand side…
Browse files Browse the repository at this point in the history
… 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 <[email protected]>

* Update vm/src/types/errors/program_errors.rs

typo

Co-authored-by: Gabriel Bosio <[email protected]>

---------

Co-authored-by: Gabriel Bosio <[email protected]>
  • Loading branch information
FrancoGiachetta and gabrielbosio authored Jan 3, 2025
1 parent 052e7ce commit 87c10b3
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 67 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
2 changes: 1 addition & 1 deletion vm/src/hint_processor/builtin_hint_processor/hint_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]);

Expand Down
70 changes: 56 additions & 14 deletions vm/src/hint_processor/builtin_hint_processor/math_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -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!(
Expand All @@ -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!(
Expand Down Expand Up @@ -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!(
Expand Down
16 changes: 11 additions & 5 deletions vm/src/hint_processor/hint_processor_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -145,8 +151,8 @@ impl From<Reference> 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,
Expand Down
35 changes: 20 additions & 15 deletions vm/src/hint_processor/hint_processor_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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!(
Expand All @@ -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()),
Expand All @@ -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(
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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!(
Expand All @@ -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());
Expand All @@ -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()),
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down
10 changes: 5 additions & 5 deletions vm/src/serde/deserialize_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
Loading

0 comments on commit 87c10b3

Please sign in to comment.