1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

add test for /0, adjust field implementation to recover from error

This commit is contained in:
schaeff 2020-11-20 15:10:01 +00:00
parent a6329fa37f
commit 1abf7d383f
7 changed files with 43 additions and 13 deletions

View file

@ -0,0 +1,3 @@
def main(field x):
field y = 1 / x
return

View file

@ -0,0 +1,3 @@
def main(u8 x):
u8 y = 0x01 / x
return

View file

@ -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()
}
}

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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()
}
}