Skip to content

Commit 87c10b3

Browse files
Add support for subtractions contenting references as right hand side operands (#1898)
* take into account the sign of the reference * resolve conflicts * fix issue * add test with negated outer reference * update changelog * test passing * explain unreachable * format * fix test * fix test and changelog * revert changes in custom_hint/custom_hint.rs * remove unwanted files * Update CHANGELOG.md Co-authored-by: Gabriel Bosio <[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]>
1 parent 052e7ce commit 87c10b3

File tree

10 files changed

+162
-67
lines changed

10 files changed

+162
-67
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#### [2.0.0-rc2] - 2024-12-12
1212

13+
* feat: Add support for subtractions containing references as right hand side operands [#1898](https://github.com/lambdaclass/cairo-vm/pull/1898)
14+
1315
* fix: Change wildcard getrandom dependency.
1416

1517
* Update starknet-crypto to 0.7.3, removing the old FieldElement completly in favour of the new Felt (that is Copy).

vm/src/hint_processor/builtin_hint_processor/hint_utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ mod tests {
149149
fn get_ptr_from_var_name_immediate_value() {
150150
let mut vm = vm!();
151151
vm.segments = segments![((1, 0), (0, 0))];
152-
let mut hint_ref = HintReference::new(0, 0, true, false);
152+
let mut hint_ref = HintReference::new(0, 0, true, false, true);
153153
hint_ref.offset2 = OffsetValue::Value(2);
154154
let ids_data = HashMap::from([("imm".to_string(), hint_ref)]);
155155

vm/src/hint_processor/builtin_hint_processor/math_utils.rs

+56-14
Original file line numberDiff line numberDiff line change
@@ -2053,8 +2053,14 @@ mod tests {
20532053
//Create ids
20542054
let ids_data = HashMap::from([
20552055
("value".to_string(), HintReference::new_simple(-4)),
2056-
("low".to_string(), HintReference::new(-3, 0, true, true)),
2057-
("high".to_string(), HintReference::new(-3, 1, true, true)),
2056+
(
2057+
"low".to_string(),
2058+
HintReference::new(-3, 0, true, true, true),
2059+
),
2060+
(
2061+
"high".to_string(),
2062+
HintReference::new(-3, 1, true, true, true),
2063+
),
20582064
]);
20592065
//Execute the hint
20602066
assert_matches!(
@@ -2131,8 +2137,14 @@ mod tests {
21312137
//Create ids_data & hint_data
21322138
let ids_data = HashMap::from([
21332139
("value".to_string(), HintReference::new_simple(-4)),
2134-
("low".to_string(), HintReference::new(-3, 0, true, true)),
2135-
("high".to_string(), HintReference::new(-3, 1, true, true)),
2140+
(
2141+
"low".to_string(),
2142+
HintReference::new(-3, 0, true, true, true),
2143+
),
2144+
(
2145+
"high".to_string(),
2146+
HintReference::new(-3, 1, true, true, true),
2147+
),
21362148
]);
21372149

21382150
//Execute the hint
@@ -2175,8 +2187,14 @@ mod tests {
21752187
//Create ids_data & hint_data
21762188
let ids_data = HashMap::from([
21772189
("value".to_string(), HintReference::new_simple(-4)),
2178-
("low".to_string(), HintReference::new(-3, 0, true, true)),
2179-
("high".to_string(), HintReference::new(-3, 1, true, true)),
2190+
(
2191+
"low".to_string(),
2192+
HintReference::new(-3, 0, true, true, true),
2193+
),
2194+
(
2195+
"high".to_string(),
2196+
HintReference::new(-3, 1, true, true, true),
2197+
),
21802198
]);
21812199
//Execute the hint
21822200
assert_matches!(
@@ -2213,8 +2231,14 @@ mod tests {
22132231
//Create ids_data & hint_data
22142232
let ids_data = HashMap::from([
22152233
("value".to_string(), HintReference::new_simple(-4)),
2216-
("low".to_string(), HintReference::new(-3, 0, true, true)),
2217-
("high".to_string(), HintReference::new(-3, 1, true, true)),
2234+
(
2235+
"low".to_string(),
2236+
HintReference::new(-3, 0, true, true, true),
2237+
),
2238+
(
2239+
"high".to_string(),
2240+
HintReference::new(-3, 1, true, true, true),
2241+
),
22182242
]);
22192243
//Execute the hint
22202244
assert_matches!(
@@ -2251,8 +2275,14 @@ mod tests {
22512275
//Create ids
22522276
let ids_data = HashMap::from([
22532277
("value".to_string(), HintReference::new_simple(-4)),
2254-
("low".to_string(), HintReference::new(-3, 0, true, true)),
2255-
("high".to_string(), HintReference::new(-3, 1, true, true)),
2278+
(
2279+
"low".to_string(),
2280+
HintReference::new(-3, 0, true, true, true),
2281+
),
2282+
(
2283+
"high".to_string(),
2284+
HintReference::new(-3, 1, true, true, true),
2285+
),
22562286
]);
22572287
//Execute the hint
22582288
assert_matches!(
@@ -2277,8 +2307,14 @@ mod tests {
22772307
//Create ids
22782308
let ids_data = HashMap::from([
22792309
("value".to_string(), HintReference::new_simple(-4)),
2280-
("low".to_string(), HintReference::new(-3, 0, true, true)),
2281-
("high".to_string(), HintReference::new(-3, 1, true, true)),
2310+
(
2311+
"low".to_string(),
2312+
HintReference::new(-3, 0, true, true, true),
2313+
),
2314+
(
2315+
"high".to_string(),
2316+
HintReference::new(-3, 1, true, true, true),
2317+
),
22822318
]);
22832319
//Execute the hint
22842320
assert_matches!(
@@ -2315,8 +2351,14 @@ mod tests {
23152351
//Create ids
23162352
let ids_data = HashMap::from([
23172353
("value".to_string(), HintReference::new_simple(-4)),
2318-
("low".to_string(), HintReference::new(-3, 0, true, true)),
2319-
("high".to_string(), HintReference::new(-3, 1, true, true)),
2354+
(
2355+
"low".to_string(),
2356+
HintReference::new(-3, 0, true, true, true),
2357+
),
2358+
(
2359+
"high".to_string(),
2360+
HintReference::new(-3, 1, true, true, true),
2361+
),
23202362
]);
23212363
//Execute the hint
23222364
assert_matches!(

vm/src/hint_processor/hint_processor_definition.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pub struct HintReference {
112112
impl HintReference {
113113
pub fn new_simple(offset1: i32) -> Self {
114114
HintReference {
115-
offset1: OffsetValue::Reference(Register::FP, offset1, false),
115+
offset1: OffsetValue::Reference(Register::FP, offset1, false, true),
116116
offset2: OffsetValue::Value(0),
117117
ap_tracking_data: None,
118118
outer_dereference: true,
@@ -121,9 +121,15 @@ impl HintReference {
121121
}
122122
}
123123

124-
pub fn new(offset1: i32, offset2: i32, inner_dereference: bool, dereference: bool) -> Self {
124+
pub fn new(
125+
offset1: i32,
126+
offset2: i32,
127+
inner_dereference: bool,
128+
dereference: bool,
129+
is_positive: bool,
130+
) -> Self {
125131
HintReference {
126-
offset1: OffsetValue::Reference(Register::FP, offset1, inner_dereference),
132+
offset1: OffsetValue::Reference(Register::FP, offset1, inner_dereference, is_positive),
127133
offset2: OffsetValue::Value(offset2),
128134
ap_tracking_data: None,
129135
outer_dereference: dereference,
@@ -145,8 +151,8 @@ impl From<Reference> for HintReference {
145151
&reference.value_address.offset1,
146152
&reference.value_address.offset2,
147153
) {
148-
(OffsetValue::Reference(Register::AP, _, _), _)
149-
| (_, OffsetValue::Reference(Register::AP, _, _)) => {
154+
(OffsetValue::Reference(Register::AP, _, _, _), _)
155+
| (_, OffsetValue::Reference(Register::AP, _, _, _)) => {
150156
Some(reference.ap_tracking_data.clone())
151157
}
152158
_ => None,

vm/src/hint_processor/hint_processor_utils.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@ pub fn get_maybe_relocatable_from_reference(
7070
&hint_reference.ap_tracking_data,
7171
ap_tracking,
7272
)?;
73-
let mut val = offset1.add(&offset2).ok()?;
73+
let mut val = match hint_reference.offset2 {
74+
OffsetValue::Reference(_, _, _, true)
75+
| OffsetValue::Immediate(_)
76+
| OffsetValue::Value(_) => offset1.add(&offset2).ok()?,
77+
OffsetValue::Reference(_, _, _, false) => offset1.sub(&offset2).ok()?,
78+
};
7479
if hint_reference.inner_dereference && hint_reference.outer_dereference {
7580
val = vm.get_maybe(&val)?;
7681
}
@@ -139,7 +144,7 @@ fn get_offset_value(
139144
match offset_value {
140145
OffsetValue::Immediate(f) => Some(f.into()),
141146
OffsetValue::Value(v) => Some(Felt252::from(*v).into()),
142-
OffsetValue::Reference(register, offset, deref) => {
147+
OffsetValue::Reference(register, offset, deref, _) => {
143148
let addr = (if matches!(register, Register::FP) {
144149
vm.get_fp()
145150
} else {
@@ -176,7 +181,7 @@ mod tests {
176181
// Reference: cast(2, felt)
177182
let mut vm = vm!();
178183
vm.segments = segments![((1, 0), 0)];
179-
let mut hint_ref = HintReference::new(0, 0, false, false);
184+
let mut hint_ref = HintReference::new(0, 0, false, false, true);
180185
hint_ref.offset1 = OffsetValue::Immediate(Felt252::from(2));
181186

182187
assert_eq!(
@@ -191,8 +196,8 @@ mod tests {
191196
fn get_offset_value_reference_valid() {
192197
let mut vm = vm!();
193198
vm.segments = segments![((1, 0), 0)];
194-
let mut hint_ref = HintReference::new(0, 0, false, true);
195-
hint_ref.offset1 = OffsetValue::Reference(Register::FP, 2_i32, false);
199+
let mut hint_ref = HintReference::new(0, 0, false, true, true);
200+
hint_ref.offset1 = OffsetValue::Reference(Register::FP, 2_i32, false, true);
196201

197202
assert_matches!(
198203
get_offset_value(&vm, &hint_ref.offset1, &hint_ref.ap_tracking_data, &ApTracking::new()),
@@ -205,8 +210,8 @@ mod tests {
205210
fn get_offset_value_invalid() {
206211
let mut vm = vm!();
207212
vm.segments = segments![((1, 0), 0)];
208-
let mut hint_ref = HintReference::new(0, 0, false, true);
209-
hint_ref.offset1 = OffsetValue::Reference(Register::FP, -2_i32, false);
213+
let mut hint_ref = HintReference::new(0, 0, false, true, true);
214+
hint_ref.offset1 = OffsetValue::Reference(Register::FP, -2_i32, false, true);
210215

211216
assert_matches!(
212217
get_offset_value(
@@ -228,7 +233,7 @@ mod tests {
228233
assert_matches!(
229234
get_ptr_from_reference(
230235
&vm,
231-
&HintReference::new(0, 0, false, false),
236+
&HintReference::new(0, 0, false, false, true),
232237
&ApTracking::new()
233238
),
234239
Ok(x) if x == relocatable!(1, 0)
@@ -244,7 +249,7 @@ mod tests {
244249
assert_matches!(
245250
get_ptr_from_reference(
246251
&vm,
247-
&HintReference::new(0, 0, false, true),
252+
&HintReference::new(0, 0, false, true, true),
248253
&ApTracking::new()
249254
),
250255
Ok(x) if x == relocatable!(3, 0)
@@ -256,7 +261,7 @@ mod tests {
256261
fn get_ptr_from_reference_with_dereference_and_imm() {
257262
let mut vm = vm!();
258263
vm.segments = segments![((1, 0), (4, 0))];
259-
let mut hint_ref = HintReference::new(0, 0, true, false);
264+
let mut hint_ref = HintReference::new(0, 0, true, false, true);
260265
hint_ref.offset2 = OffsetValue::Value(2);
261266

262267
assert_matches!(
@@ -270,7 +275,7 @@ mod tests {
270275
fn compute_addr_from_reference_no_regiter_in_reference() {
271276
let mut vm = vm!();
272277
vm.segments = segments![((1, 0), (4, 0))];
273-
let mut hint_reference = HintReference::new(0, 0, false, false);
278+
let mut hint_reference = HintReference::new(0, 0, false, false, true);
274279
hint_reference.offset1 = OffsetValue::Immediate(Felt252::from(2_i32));
275280

276281
assert!(compute_addr_from_reference(&hint_reference, &vm, &ApTracking::new()).is_none());
@@ -282,8 +287,8 @@ mod tests {
282287
let mut vm = vm!();
283288
vm.segments = segments![((1, 0), 4)];
284289
// vm.run_context.fp = -1;
285-
let mut hint_reference = HintReference::new(0, 0, false, false);
286-
hint_reference.offset1 = OffsetValue::Reference(Register::FP, -1, true);
290+
let mut hint_reference = HintReference::new(0, 0, false, false, true);
291+
hint_reference.offset1 = OffsetValue::Reference(Register::FP, -1, true, true);
287292

288293
assert_matches!(
289294
compute_addr_from_reference(&hint_reference, &vm, &ApTracking::new()),
@@ -356,7 +361,7 @@ mod tests {
356361
((0, 5), 3) // [[[fp + 2] + 2]] -> [(0, 5)] -> 3
357362
];
358363
let hint_ref = HintReference {
359-
offset1: OffsetValue::Reference(Register::FP, 2, true),
364+
offset1: OffsetValue::Reference(Register::FP, 2, true, true),
360365
offset2: OffsetValue::Value(2),
361366
outer_dereference: true,
362367
inner_dereference: true,
@@ -381,7 +386,7 @@ mod tests {
381386
];
382387
// [fp + 4] + (-5) = 8 - 5 = 3
383388
let hint_ref = HintReference {
384-
offset1: OffsetValue::Reference(Register::FP, 4, true),
389+
offset1: OffsetValue::Reference(Register::FP, 4, true, true),
385390
offset2: OffsetValue::Immediate(Felt252::from(-5)),
386391
outer_dereference: false,
387392
inner_dereference: false,

vm/src/serde/deserialize_program.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ pub struct Reference {
275275
pub enum OffsetValue {
276276
Immediate(Felt252),
277277
Value(i32),
278-
Reference(Register, i32, bool),
278+
Reference(Register, i32, bool, bool),
279279
}
280280

281281
#[cfg_attr(feature = "test_utils", derive(Arbitrary))]
@@ -714,7 +714,7 @@ mod tests {
714714
},
715715
pc: Some(0),
716716
value_address: ValueAddress {
717-
offset1: OffsetValue::Reference(Register::FP, -4, false),
717+
offset1: OffsetValue::Reference(Register::FP, -4, false, true),
718718
offset2: OffsetValue::Value(0),
719719
outer_dereference: true,
720720
inner_dereference: false,
@@ -728,7 +728,7 @@ mod tests {
728728
},
729729
pc: Some(0),
730730
value_address: ValueAddress {
731-
offset1: OffsetValue::Reference(Register::FP, -3, false),
731+
offset1: OffsetValue::Reference(Register::FP, -3, false, true),
732732
offset2: OffsetValue::Value(0),
733733
outer_dereference: true,
734734
inner_dereference: false,
@@ -742,7 +742,7 @@ mod tests {
742742
},
743743
pc: Some(0),
744744
value_address: ValueAddress {
745-
offset1: OffsetValue::Reference(Register::FP, -3, true),
745+
offset1: OffsetValue::Reference(Register::FP, -3, true, true),
746746
offset2: OffsetValue::Immediate(Felt252::from(2)),
747747
outer_dereference: false,
748748
inner_dereference: false,
@@ -756,7 +756,7 @@ mod tests {
756756
},
757757
pc: Some(0),
758758
value_address: ValueAddress {
759-
offset1: OffsetValue::Reference(Register::FP, 0, false),
759+
offset1: OffsetValue::Reference(Register::FP, 0, false, true),
760760
offset2: OffsetValue::Value(0),
761761
outer_dereference: true,
762762
inner_dereference: false,

0 commit comments

Comments
 (0)