add test for /0, adjust field implementation to recover from error
This commit is contained in:
parent
a6329fa37f
commit
1abf7d383f
7 changed files with 43 additions and 13 deletions
3
zokrates_cli/examples/runtime_errors/div_zero_field.zok
Normal file
3
zokrates_cli/examples/runtime_errors/div_zero_field.zok
Normal file
|
@ -0,0 +1,3 @@
|
|||
def main(field x):
|
||||
field y = 1 / x
|
||||
return
|
3
zokrates_cli/examples/runtime_errors/div_zero_uint.zok
Normal file
3
zokrates_cli/examples/runtime_errors/div_zero_uint.zok
Normal file
|
@ -0,0 +1,3 @@
|
|||
def main(u8 x):
|
||||
u8 y = 0x01 / x
|
||||
return
|
|
@ -263,7 +263,7 @@ impl<T: Field> Div<&T> for LinComb<T> {
|
|||
type Output = LinComb<T>;
|
||||
|
||||
fn div(self, scalar: &T) -> LinComb<T> {
|
||||
self * &scalar.inverse_mul()
|
||||
self * &scalar.inverse_mul().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,10 @@ impl Interpreter {
|
|||
let res = match s {
|
||||
Solver::ConditionEq => match inputs[0].is_zero() {
|
||||
true => vec![T::zero(), T::one()],
|
||||
false => vec![T::one(), T::one() / &inputs[0]],
|
||||
false => vec![
|
||||
T::one(),
|
||||
T::one().checked_div(&inputs[0]).unwrap_or(T::one()),
|
||||
],
|
||||
},
|
||||
Solver::Bits(bit_width) => {
|
||||
let mut num = inputs[0].clone();
|
||||
|
@ -183,7 +186,10 @@ impl Interpreter {
|
|||
let c = inputs[2].clone();
|
||||
vec![a * (b - c.clone()) + c]
|
||||
}
|
||||
Solver::Div => vec![inputs[0].clone() / inputs[1].clone()],
|
||||
Solver::Div => vec![inputs[0]
|
||||
.clone()
|
||||
.checked_div(&inputs[1])
|
||||
.unwrap_or(T::one())],
|
||||
Solver::EuclideanDiv => {
|
||||
use num::CheckedDiv;
|
||||
|
||||
|
|
|
@ -1,2 +1,6 @@
|
|||
def main(u8 x, u8 y) -> u8:
|
||||
assert(0x02 / 0x02 == 0x01)
|
||||
assert(0x04 / 0x02 == 0x02)
|
||||
assert(0x05 / 0x02 == 0x02)
|
||||
assert(0xff / 0x03 == 0x55)
|
||||
return x / y
|
|
@ -1,2 +1,7 @@
|
|||
def main(u8 x, u8 y) -> u8:
|
||||
assert(0x02 % 0x02 == 0x00)
|
||||
assert(0x04 % 0x02 == 0x00)
|
||||
assert(0x05 % 0x02 == 0x01)
|
||||
assert(0xff % 0x03 == 0x00)
|
||||
assert(0xff % 0x01 == 0x00)
|
||||
return x % y
|
|
@ -10,7 +10,7 @@ use algebra_core::PairingEngine;
|
|||
use bellman_ce::pairing::ff::ScalarEngine;
|
||||
use bellman_ce::pairing::Engine;
|
||||
use num_bigint::BigUint;
|
||||
use num_traits::{One, Zero};
|
||||
use num_traits::{CheckedDiv, One, Zero};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::{From, TryFrom};
|
||||
use std::fmt::{Debug, Display};
|
||||
|
@ -61,8 +61,8 @@ pub trait Field:
|
|||
+ for<'a> Sub<&'a Self, Output = Self>
|
||||
+ Mul<Self, Output = Self>
|
||||
+ for<'a> Mul<&'a Self, Output = Self>
|
||||
+ CheckedDiv
|
||||
+ Div<Self, Output = Self>
|
||||
+ for<'a> Div<&'a Self, Output = Self>
|
||||
+ Pow<usize, Output = Self>
|
||||
+ Pow<Self, Output = Self>
|
||||
+ for<'a> Pow<&'a Self, Output = Self>
|
||||
|
@ -78,7 +78,7 @@ pub trait Field:
|
|||
/// Returns this `Field`'s contents as decimal string
|
||||
fn to_dec_string(&self) -> String;
|
||||
/// Returns the multiplicative inverse, i.e.: self * self.inverse_mul() = Self::one()
|
||||
fn inverse_mul(&self) -> Self;
|
||||
fn inverse_mul(&self) -> Option<Self>;
|
||||
/// Returns the smallest value that can be represented by this field type.
|
||||
fn min_value() -> Self;
|
||||
/// Returns the largest value that can be represented by this field type.
|
||||
|
@ -129,7 +129,7 @@ mod prime_field {
|
|||
use lazy_static::lazy_static;
|
||||
use num_bigint::{BigInt, BigUint, Sign, ToBigInt};
|
||||
use num_integer::Integer;
|
||||
use num_traits::{One, Zero};
|
||||
use num_traits::{CheckedDiv, One, Zero};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::convert::From;
|
||||
use std::convert::TryFrom;
|
||||
|
@ -173,11 +173,14 @@ mod prime_field {
|
|||
self.value.to_str_radix(10)
|
||||
}
|
||||
|
||||
fn inverse_mul(&self) -> FieldPrime {
|
||||
fn inverse_mul(&self) -> Option<FieldPrime> {
|
||||
let (b, s, _) = extended_euclid(&self.value, &*P);
|
||||
assert_eq!(b, BigInt::one());
|
||||
FieldPrime {
|
||||
value: &s - s.div_floor(&*P) * &*P,
|
||||
if b == BigInt::one() {
|
||||
Some(FieldPrime {
|
||||
value: &s - s.div_floor(&*P) * &*P,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn min_value() -> FieldPrime {
|
||||
|
@ -387,11 +390,17 @@ mod prime_field {
|
|||
}
|
||||
}
|
||||
|
||||
impl CheckedDiv for FieldPrime {
|
||||
fn checked_div(&self, other: &FieldPrime) -> Option<FieldPrime> {
|
||||
other.inverse_mul().map(|inv| inv * self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<FieldPrime> for FieldPrime {
|
||||
type Output = FieldPrime;
|
||||
|
||||
fn div(self, other: FieldPrime) -> FieldPrime {
|
||||
self * other.inverse_mul()
|
||||
self.checked_div(&other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,7 +408,7 @@ mod prime_field {
|
|||
type Output = FieldPrime;
|
||||
|
||||
fn div(self, other: &FieldPrime) -> FieldPrime {
|
||||
self / other.clone()
|
||||
self.checked_div(&other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue