Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MathError for math operations #855

Merged
merged 27 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
092af21
Use only option for Memory.get
fmoletta Feb 17, 2023
66d4161
Fix some tests + refactor range_check validation
fmoletta Feb 17, 2023
f41c5b5
use proper error for get_memory_holes
fmoletta Feb 17, 2023
d732995
Move MaybeRelocatable methods get_int_ref & get_reloctable to Option
fmoletta Feb 17, 2023
18e8fe0
Fix tests
fmoletta Feb 17, 2023
2016148
Clippy
fmoletta Feb 17, 2023
eaa7ab1
Fix `CairoRunner::write_output` so that it prints missing and relocat…
fmoletta Feb 17, 2023
9669874
Move errors outputed by math_utils to MathError
fmoletta Feb 17, 2023
68f9c80
Start moving relocatable operations to MathError
fmoletta Feb 17, 2023
219791c
Merge branch 'main' of github.com:lambdaclass/cairo-rs into memory-ge…
fmoletta Feb 22, 2023
f62defe
Merge branch 'memory-get-option' into math-error
fmoletta Feb 22, 2023
badea4e
Fix tests
fmoletta Feb 22, 2023
330bd0f
Remove math-related errors from vm error
fmoletta Feb 22, 2023
38cc165
Move conversion errors to MathError
fmoletta Feb 22, 2023
48a8819
Move type conversions to MathError
fmoletta Feb 22, 2023
34dec09
Remove unused errors
fmoletta Feb 22, 2023
70dfb0a
Clippy
fmoletta Feb 22, 2023
5e3f922
Clippy
fmoletta Feb 22, 2023
30a10f6
Simplify addition
fmoletta Feb 22, 2023
0f02553
Simplify addition
fmoletta Feb 22, 2023
e3a77db
Clippy
fmoletta Feb 22, 2023
0ff5aba
Add math_errors.rs
fmoletta Feb 23, 2023
1438944
Merge branch 'main' of github.com:lambdaclass/cairo-rs into math-error
fmoletta Feb 23, 2023
4beb4c8
Merge branch 'main' of github.com:lambdaclass/cairo-rs into math-error
fmoletta Feb 24, 2023
1b8f29e
Check for overflows in relocatable operations (#859)
fmoletta Mar 1, 2023
2553045
Merge branch 'main' of github.com:lambdaclass/cairo-rs into math-error
fmoletta Mar 2, 2023
6f0363b
Merge branch 'main' of github.com:lambdaclass/cairo-rs into math-error
fmoletta Mar 3, 2023
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: 5 additions & 3 deletions src/hint_processor/builtin_hint_processor/blake2s_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ pub fn blake2s_add_uint256_bigend(
#[cfg(test)]
mod tests {
use super::*;
use crate::types::errors::math_errors::MathError;
use crate::vm::vm_memory::memory_segments::MemorySegmentManager;
use crate::{
any_box,
Expand Down Expand Up @@ -249,9 +250,10 @@ mod tests {
//Execute the hint
assert_matches!(
run_hint!(vm, ids_data, hint_code),
Err(HintError::Internal(VirtualMachineError::CantSubOffset(
5, 26
)))
Err(HintError::Math(MathError::RelocatableSubNegOffset(
x,
y
))) if x == relocatable!(2,5) && y == 26
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
hint_processor_definition::HintReference,
},
serde::deserialize_program::ApTracking,
types::relocatable::MaybeRelocatable,
types::{errors::math_errors::MathError, relocatable::MaybeRelocatable},
vm::{
errors::{hint_errors::HintError, vm_errors::VirtualMachineError},
vm_core::VirtualMachine,
Expand Down Expand Up @@ -235,9 +235,9 @@ pub(crate) fn maybe_reloc_vec_to_u64_array(
.iter()
.map(|n| match n {
Some(Cow::Owned(MaybeRelocatable::Int(ref num)))
| Some(Cow::Borrowed(MaybeRelocatable::Int(ref num))) => {
num.to_u64().ok_or(VirtualMachineError::BigintToU64Fail)
}
| Some(Cow::Borrowed(MaybeRelocatable::Int(ref num))) => num
.to_u64()
.ok_or_else(|| MathError::FeltToU64Conversion(num.clone()).into()),
_ => Err(VirtualMachineError::ExpectedIntAtRange(
n.as_ref().map(|x| x.as_ref().to_owned()),
)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ use crate::{
hint_processor_utils::felt_to_usize,
},
serde::deserialize_program::ApTracking,
types::exec_scope::ExecutionScopes,
vm::{
errors::{hint_errors::HintError, vm_errors::VirtualMachineError},
vm_core::VirtualMachine,
},
types::{errors::math_errors::MathError, exec_scope::ExecutionScopes},
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
};
use felt::Felt;
use num_traits::{Signed, ToPrimitive};
Expand Down Expand Up @@ -67,7 +64,7 @@ pub fn find_element(
}
let n_elms_iter: i32 = n_elms
.to_i32()
.ok_or_else(|| VirtualMachineError::OffsetExceeded(n_elms.into_owned()))?;
.ok_or_else(|| MathError::FeltToI32Conversion(n_elms.into_owned()))?;

for i in 0..n_elms_iter {
let iter_key = vm
Expand Down
8 changes: 3 additions & 5 deletions src/hint_processor/builtin_hint_processor/secp/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ pub fn get_point_from_x(
#[cfg(test)]
mod tests {
use super::*;
use crate::types::errors::math_errors::MathError;
use crate::vm::vm_memory::memory_segments::MemorySegmentManager;
use crate::{
any_box,
Expand All @@ -160,10 +161,7 @@ mod tests {
},
types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable},
utils::test_utils::*,
vm::{
errors::{memory_errors::MemoryError, vm_errors::VirtualMachineError},
vm_memory::memory::Memory,
},
vm::{errors::memory_errors::MemoryError, vm_memory::memory::Memory},
};
use assert_matches::assert_matches;
use num_traits::Zero;
Expand Down Expand Up @@ -222,7 +220,7 @@ mod tests {
.collect()
),
Err(
HintError::Internal(VirtualMachineError::SafeDivFailBigInt(
HintError::Math(MathError::SafeDivFailBigInt(
x,
y,
)
Expand Down
22 changes: 13 additions & 9 deletions src/hint_processor/builtin_hint_processor/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
hint_processor_definition::HintReference,
},
serde::deserialize_program::ApTracking,
types::relocatable::MaybeRelocatable,
types::{errors::math_errors::MathError, relocatable::MaybeRelocatable},
vm::{
errors::{hint_errors::HintError, vm_errors::VirtualMachineError},
vm_core::VirtualMachine,
Expand All @@ -22,14 +22,18 @@ pub fn set_add(
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let set_ptr = get_ptr_from_var_name("set_ptr", vm, ids_data, ap_tracking)?;
let elm_size = get_integer_from_var_name("elm_size", vm, ids_data, ap_tracking)?
.to_usize()
.ok_or(VirtualMachineError::BigintToUsizeFail)?;
let elm_size =
get_integer_from_var_name("elm_size", vm, ids_data, ap_tracking).and_then(|x| {
x.to_usize()
.ok_or_else(|| MathError::FeltToUsizeConversion(x.into_owned()).into())
})?;
let elm_ptr = get_ptr_from_var_name("elm_ptr", vm, ids_data, ap_tracking)?;
let set_end_ptr = get_ptr_from_var_name("set_end_ptr", vm, ids_data, ap_tracking)?;

if elm_size.is_zero() {
Err(VirtualMachineError::ValueNotPositive(Felt::new(elm_size)))?;
Err(HintError::AssertionFailed(String::from(
"assert ids.elm_size > 0",
)))?;
}
let elm = vm
.get_range(&MaybeRelocatable::from(elm_ptr), elm_size)
Expand Down Expand Up @@ -158,7 +162,7 @@ mod tests {
let (mut vm, ids_data) = init_vm_ids_data(None, Some(-2), None, None);
assert_matches!(
run_hint!(vm, ids_data, HINT_CODE),
Err(HintError::Internal(VirtualMachineError::BigintToUsizeFail))
Err(HintError::Math(MathError::FeltToUsizeConversion(_)))
);
}

Expand All @@ -167,9 +171,9 @@ mod tests {
let (mut vm, ids_data) = init_vm_ids_data(None, Some(0), None, None);
assert_matches!(
run_hint!(vm, ids_data, HINT_CODE),
Err(HintError::Internal(VirtualMachineError::ValueNotPositive(
int
))) if int.is_zero()
Err(HintError::AssertionFailed(
m
)) if m == *"assert ids.elm_size > 0"
);
}
#[test]
Expand Down
15 changes: 7 additions & 8 deletions src/hint_processor/hint_processor_utils.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use crate::{
serde::deserialize_program::{ApTracking, OffsetValue},
types::{
errors::math_errors::MathError,
instruction::Register,
relocatable::{MaybeRelocatable, Relocatable},
},
vm::{
errors::{hint_errors::HintError, vm_errors::VirtualMachineError},
vm_core::VirtualMachine,
},
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
};
use std::borrow::Cow;

Expand Down Expand Up @@ -136,14 +134,15 @@ fn apply_ap_tracking_correction(
}

//Tries to convert a Felt value to usize
pub fn felt_to_usize(felt: &Felt) -> Result<usize, VirtualMachineError> {
pub fn felt_to_usize(felt: &Felt) -> Result<usize, MathError> {
felt.to_usize()
.ok_or(VirtualMachineError::BigintToUsizeFail)
.ok_or_else(|| MathError::FeltToUsizeConversion(felt.clone()))
}

///Tries to convert a Felt value to u32
pub fn felt_to_u32(felt: &Felt) -> Result<u32, VirtualMachineError> {
felt.to_u32().ok_or(VirtualMachineError::BigintToU32Fail)
pub fn felt_to_u32(felt: &Felt) -> Result<u32, MathError> {
felt.to_u32()
.ok_or_else(|| MathError::FeltToU32Conversion(felt.clone()))
}

fn get_offset_value_reference(
Expand Down
40 changes: 17 additions & 23 deletions src/math_utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::vm::errors::vm_errors::VirtualMachineError;
use crate::types::errors::math_errors::MathError;
use felt::Felt;
use num_bigint::{BigInt, BigUint};
use num_integer::Integer;
Expand All @@ -8,7 +8,7 @@ use std::ops::Shr;
///Returns the integer square root of the nonnegative integer n.
///This is the floor of the exact square root of n.
///Unlike math.sqrt(), this function doesn't have rounding error issues.
pub fn isqrt(n: &BigUint) -> Result<BigUint, VirtualMachineError> {
pub fn isqrt(n: &BigUint) -> Result<BigUint, MathError> {
/* # The following algorithm was copied from
# https://stackoverflow.com/questions/15390807/integer-square-root-in-python.
x = n
Expand All @@ -29,51 +29,51 @@ pub fn isqrt(n: &BigUint) -> Result<BigUint, VirtualMachineError> {
}

if !(&x.pow(2) <= n && n < &(&x + 1_u32).pow(2_u32)) {
return Err(VirtualMachineError::FailedToGetSqrt(n.clone()));
return Err(MathError::FailedToGetSqrt(n.clone()));
};
Ok(x)
}

/// Performs integer division between x and y; fails if x is not divisible by y.
pub fn safe_div(x: &Felt, y: &Felt) -> Result<Felt, VirtualMachineError> {
pub fn safe_div(x: &Felt, y: &Felt) -> Result<Felt, MathError> {
if y.is_zero() {
return Err(VirtualMachineError::DividedByZero);
return Err(MathError::DividedByZero);
}

let (q, r) = x.div_mod_floor(y);

if !r.is_zero() {
return Err(VirtualMachineError::SafeDivFail(x.clone(), y.clone()));
return Err(MathError::SafeDivFail(x.clone(), y.clone()));
}

Ok(q)
}

/// Performs integer division between x and y; fails if x is not divisible by y.
pub fn safe_div_bigint(x: &BigInt, y: &BigInt) -> Result<BigInt, VirtualMachineError> {
pub fn safe_div_bigint(x: &BigInt, y: &BigInt) -> Result<BigInt, MathError> {
if y.is_zero() {
return Err(VirtualMachineError::DividedByZero);
return Err(MathError::DividedByZero);
}

let (q, r) = x.div_mod_floor(y);

if !r.is_zero() {
return Err(VirtualMachineError::SafeDivFailBigInt(x.clone(), y.clone()));
return Err(MathError::SafeDivFailBigInt(x.clone(), y.clone()));
}

Ok(q)
}

/// Performs integer division between x and y; fails if x is not divisible by y.
pub fn safe_div_usize(x: usize, y: usize) -> Result<usize, VirtualMachineError> {
pub fn safe_div_usize(x: usize, y: usize) -> Result<usize, MathError> {
if y.is_zero() {
return Err(VirtualMachineError::DividedByZero);
return Err(MathError::DividedByZero);
}

let (q, r) = x.div_mod_floor(&y);

if !r.is_zero() {
return Err(VirtualMachineError::SafeDivFailUsize(x, y));
return Err(MathError::SafeDivFailUsize(x, y));
}

Ok(q)
Expand Down Expand Up @@ -238,7 +238,7 @@ mod tests {
let result = safe_div(&x, &y);
assert_matches!(
result,
Err(VirtualMachineError::SafeDivFail(
Err(MathError::SafeDivFail(
i, j
)) if i == Felt::new(25) && j == Felt::new(4));
}
Expand All @@ -248,7 +248,7 @@ mod tests {
let x = Felt::new(25);
let y = Felt::zero();
let result = safe_div(&x, &y);
assert_matches!(result, Err(VirtualMachineError::DividedByZero));
assert_matches!(result, Err(MathError::DividedByZero));
}

#[test]
Expand All @@ -260,16 +260,13 @@ mod tests {
fn compute_safe_div_usize_non_divisor() {
assert_matches!(
safe_div_usize(25, 4),
Err(VirtualMachineError::SafeDivFailUsize(25, 4))
Err(MathError::SafeDivFailUsize(25, 4))
);
}

#[test]
fn compute_safe_div_usize_by_zero() {
assert_matches!(
safe_div_usize(25, 0),
Err(VirtualMachineError::DividedByZero)
);
assert_matches!(safe_div_usize(25, 0), Err(MathError::DividedByZero));
}

#[test]
Expand Down Expand Up @@ -558,9 +555,6 @@ mod tests {
fn safe_div_bigint_by_zero() {
let x = BigInt::one();
let y = BigInt::zero();
assert_matches!(
safe_div_bigint(&x, &y),
Err(VirtualMachineError::DividedByZero)
)
assert_matches!(safe_div_bigint(&x, &y), Err(MathError::DividedByZero))
}
}
51 changes: 51 additions & 0 deletions src/types/errors/math_errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use felt::Felt;
use num_bigint::{BigInt, BigUint};
use thiserror::Error;

use crate::types::relocatable::{MaybeRelocatable, Relocatable};

#[derive(Debug, Error, PartialEq)]
pub enum MathError {
#[error("Can't calculate the square root of negative number: {0})")]
SqrtNegative(Felt),
#[error("{0} is not divisible by {1}")]
SafeDivFail(Felt, Felt),
#[error("{0} is not divisible by {1}")]
SafeDivFailBigInt(BigInt, BigInt),
#[error("{0} is not divisible by {1}")]
SafeDivFailBigUint(BigUint, BigUint),
#[error("{0} is not divisible by {1}")]
SafeDivFailU32(u32, u32),
#[error("Attempted to divide by zero")]
SafeDivFailUsize(usize, usize),
#[error("Attempted to divide by zero")]
DividedByZero,
#[error("Failed to calculate the square root of: {0})")]
FailedToGetSqrt(BigUint),
// Relocatable Operations
#[error("Cant convert felt: {0} to Relocatable")]
FeltToRelocatable(Felt),
#[error("Operation failed: {0} - {1}, offsets cant be negative")]
RelocatableSubNegOffset(Relocatable, usize),
#[error("Operation failed: {0} + {1}, maximum offset value exceeded")]
RelocatableAddOffsetExceeded(Relocatable, Felt),
#[error("Operation failed: {0} + {1}, cant add two relocatable values")]
RelocatableAdd(Relocatable, Relocatable),
#[error("Operation failed: {0} - {1}, cant substract two relocatable values with different segment indexes")]
RelocatableSubDiffIndex(Relocatable, Relocatable),
#[error(
"Operation failed: {0}.divmod({1}, divmod can only be performed between two integer values"
)]
DivModWrongType(MaybeRelocatable, MaybeRelocatable),
#[error("Operation failed {0} - {1}, cant substract a relocatable value from an integer")]
SubRelocatableFromInt(Felt, Relocatable),
// Type conversions
#[error("Conversion to i32 failed for Felt {0}")]
FeltToI32Conversion(Felt),
#[error("Conversion to u32 failed for Felt {0}")]
FeltToU32Conversion(Felt),
#[error("Conversion to usize failed for Felt {0}")]
FeltToUsizeConversion(Felt),
#[error("Conversion to u64 failed for Felt {0}")]
FeltToU64Conversion(Felt),
}
1 change: 1 addition & 0 deletions src/types/errors/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod math_errors;
pub mod program_errors;
Loading