diff --git a/Cargo.lock b/Cargo.lock index dbb9f99c..6920d6ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,6 +67,17 @@ dependencies = [ "ark-std", ] +[[package]] +name = "ark-bls12-381" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e1c2ad76c4f725520440b981df3ce2d635f2baa1122750c757c0cf0f3d4b74" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + [[package]] name = "ark-bn254" version = "0.2.0" @@ -2501,10 +2512,12 @@ name = "zokrates_field" version = "0.4.0" dependencies = [ "ark-bls12-377", + "ark-bls12-381", "ark-bn254", "ark-bw6-761", "ark-ec", "ark-ff", + "ark-serialize", "bellman_ce", "bincode", "lazy_static", diff --git a/changelogs/unreleased/1061-schaeff b/changelogs/unreleased/1061-schaeff new file mode 100644 index 00000000..34578f62 --- /dev/null +++ b/changelogs/unreleased/1061-schaeff @@ -0,0 +1 @@ +Use ark-ff under the hood for optimized field operations \ No newline at end of file diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index 7190b4b1..8042c3bd 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -13,7 +13,7 @@ libsnark = ["cc", "cmake", "git2"] bellman = ["bellman_ce", "pairing_ce", "ff_ce", "zokrates_field/bellman"] wasm = ["bellman_ce/nolog", "bellman_ce/wasm"] multicore = ["bellman_ce/multicore"] -ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "zokrates_field/ark", "sha2"] +ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "sha2"] [dependencies] log = "0.4" diff --git a/zokrates_field/Cargo.toml b/zokrates_field/Cargo.toml index cea2f9ec..71435ff0 100644 --- a/zokrates_field/Cargo.toml +++ b/zokrates_field/Cargo.toml @@ -5,8 +5,7 @@ authors = ["Thibaut Schaeffer ", "Guillaume Ballet ().unwrap(), - FieldPrime::from("1234245612").value - ); - } - - #[test] - fn negative_number() { - assert_eq!( - P.checked_sub(&"12".parse::().unwrap()).unwrap(), - FieldPrime::from("-12").value - ); - } - #[test] fn addition() { assert_eq!( - "65484493".parse::().unwrap(), - (FieldPrime::from("65416358") + FieldPrime::from("68135")).value + FieldPrime::from("65484493"), + FieldPrime::from("65416358") + FieldPrime::from("68135") ); assert_eq!( - "65484493".parse::().unwrap(), - (FieldPrime::from("65416358") + &FieldPrime::from("68135")).value + FieldPrime::from("65484493"), + FieldPrime::from("65416358") + &FieldPrime::from("68135") ); } #[test] fn addition_negative_small() { assert_eq!( - "3".parse::().unwrap(), - (FieldPrime::from("5") + FieldPrime::from("-2")).value + FieldPrime::from("3"), + FieldPrime::from("5") + FieldPrime::from(-2) ); assert_eq!( - "3".parse::().unwrap(), - (FieldPrime::from("5") + &FieldPrime::from("-2")).value + FieldPrime::from("3"), + FieldPrime::from("5") + &FieldPrime::from(-2) ); } #[test] fn addition_negative() { assert_eq!( - "65348223".parse::().unwrap(), - (FieldPrime::from("65416358") + FieldPrime::from("-68135")).value + FieldPrime::from("65348223"), + FieldPrime::from("65416358") + FieldPrime::from(-68135) ); assert_eq!( - "65348223".parse::().unwrap(), - (FieldPrime::from("65416358") + &FieldPrime::from("-68135")).value + FieldPrime::from("65348223"), + FieldPrime::from("65416358") + &FieldPrime::from(-68135) ); } #[test] fn subtraction() { assert_eq!( - "65348223".parse::().unwrap(), - (FieldPrime::from("65416358") - FieldPrime::from("68135")).value + FieldPrime::from("65348223"), + FieldPrime::from("65416358") - FieldPrime::from("68135") ); assert_eq!( - "65348223".parse::().unwrap(), - (FieldPrime::from("65416358") - &FieldPrime::from("68135")).value + FieldPrime::from("65348223"), + FieldPrime::from("65416358") - &FieldPrime::from("68135") ); } #[test] fn subtraction_negative() { assert_eq!( - "65484493".parse::().unwrap(), - (FieldPrime::from("65416358") - FieldPrime::from("-68135")).value + FieldPrime::from("65484493"), + FieldPrime::from("65416358") - FieldPrime::from(-68135) ); assert_eq!( - "65484493".parse::().unwrap(), - (FieldPrime::from("65416358") - &FieldPrime::from("-68135")).value + FieldPrime::from("65484493"), + FieldPrime::from("65416358") - &FieldPrime::from(-68135) ); } #[test] fn subtraction_overflow() { assert_eq!( - "21888242871839275222246405745257275088548364400416034343698204186575743147394" - .parse::() - .unwrap(), - (FieldPrime::from("68135") - FieldPrime::from("65416358")).value + FieldPrime::from( + "21888242871839275222246405745257275088548364400416034343698204186575743147394" + ), + FieldPrime::from("68135") - FieldPrime::from("65416358") ); assert_eq!( - "21888242871839275222246405745257275088548364400416034343698204186575743147394" - .parse::() - .unwrap(), - (FieldPrime::from("68135") - &FieldPrime::from("65416358")).value + FieldPrime::from( + "21888242871839275222246405745257275088548364400416034343698204186575743147394" + ), + FieldPrime::from("68135") - &FieldPrime::from("65416358") ); } #[test] fn multiplication() { assert_eq!( - "13472".parse::().unwrap(), - (FieldPrime::from("32") * FieldPrime::from("421")).value + FieldPrime::from("13472"), + FieldPrime::from("32") * FieldPrime::from("421") ); assert_eq!( - "13472".parse::().unwrap(), - (FieldPrime::from("32") * &FieldPrime::from("421")).value + FieldPrime::from("13472"), + FieldPrime::from("32") * &FieldPrime::from("421") ); } #[test] fn multiplication_negative() { assert_eq!( - "21888242871839275222246405745257275088548364400416034343698204186575808014369" - .parse::() - .unwrap(), - (FieldPrime::from("54") * FieldPrime::from("-8912")).value + FieldPrime::from( + "21888242871839275222246405745257275088548364400416034343698204186575808014369" + ), + FieldPrime::from("54") * FieldPrime::from(-8912) ); assert_eq!( - "21888242871839275222246405745257275088548364400416034343698204186575808014369" - .parse::() - .unwrap(), - (FieldPrime::from("54") * &FieldPrime::from("-8912")).value + FieldPrime::from( + "21888242871839275222246405745257275088548364400416034343698204186575808014369" + ), + FieldPrime::from("54") * &FieldPrime::from(-8912) ); } #[test] fn multiplication_two_negative() { assert_eq!( - "648".parse::().unwrap(), - (FieldPrime::from("-54") * FieldPrime::from("-12")).value + FieldPrime::from("648"), + FieldPrime::from(-54) * FieldPrime::from(-12) ); assert_eq!( - "648".parse::().unwrap(), - (FieldPrime::from("-54") * &FieldPrime::from("-12")).value + FieldPrime::from("648"), + FieldPrime::from(-54) * &FieldPrime::from(-12) ); } #[test] fn multiplication_overflow() { assert_eq!( - "6042471409729479866150380306128222617399890671095126975526159292198160466142" - .parse::() - .unwrap(), - (FieldPrime::from( + FieldPrime::from( + "6042471409729479866150380306128222617399890671095126975526159292198160466142" + ), + FieldPrime::from( "21888242871839225222246405785257275088694311157297823662689037894645225727" - ) * FieldPrime::from("218882428715392752222464057432572755886923")) - .value + ) * FieldPrime::from("218882428715392752222464057432572755886923") ); assert_eq!( - "6042471409729479866150380306128222617399890671095126975526159292198160466142" - .parse::() - .unwrap(), - (FieldPrime::from( + FieldPrime::from( + "6042471409729479866150380306128222617399890671095126975526159292198160466142" + ), + FieldPrime::from( "21888242871839225222246405785257275088694311157297823662689037894645225727" - ) * &FieldPrime::from("218882428715392752222464057432572755886923")) - .value + ) * &FieldPrime::from("218882428715392752222464057432572755886923") ); } @@ -203,6 +181,36 @@ mod tests { ); } + #[test] + fn required_bits() { + assert_eq!(FieldPrime::get_required_bits(), 254); + } + + #[test] + fn bits() { + assert_eq!(FieldPrime::from(0).bits(), 1); + assert_eq!(FieldPrime::from(1).bits(), 1); + assert_eq!(FieldPrime::from(2).bits(), 2); + assert_eq!(FieldPrime::from(3).bits(), 2); + assert_eq!(FieldPrime::from(4).bits(), 3); + } + + #[test] + fn to_biguint() { + assert_eq!( + FieldPrime::try_from(FieldPrime::from(2).to_biguint()), + Ok(FieldPrime::from(2)) + ); + assert_eq!( + FieldPrime::try_from(FieldPrime::from(0).to_biguint()), + Ok(FieldPrime::from(0)) + ); + assert_eq!( + FieldPrime::try_from(FieldPrime::max_value().to_biguint()), + Ok(FieldPrime::max_value()) + ); + } + #[test] fn division_negative() { let res = FieldPrime::from(-54) / FieldPrime::from(12); @@ -218,8 +226,8 @@ mod tests { #[test] fn pow_usize() { assert_eq!( - "614787626176508399616".parse::().unwrap(), - (FieldPrime::from("54").pow(12)).value + FieldPrime::from("614787626176508399616"), + FieldPrime::from("54").pow(12) ); } @@ -275,72 +283,6 @@ mod tests { } } - #[test] - fn bigint_assertions() { - let x = BigInt::parse_bytes(b"65", 10).unwrap(); - assert_eq!(&x + &x, BigInt::parse_bytes(b"130", 10).unwrap()); - assert_eq!( - "1".parse::().unwrap(), - "3".parse::() - .unwrap() - .div_floor(&"2".parse::().unwrap()) - ); - assert_eq!( - "-2".parse::().unwrap(), - "-3".parse::() - .unwrap() - .div_floor(&"2".parse::().unwrap()) - ); - } - - #[test] - fn test_extended_euclid() { - assert_eq!( - ( - ToBigInt::to_bigint(&1).unwrap(), - ToBigInt::to_bigint(&-9).unwrap(), - ToBigInt::to_bigint(&47).unwrap() - ), - extended_euclid( - &ToBigInt::to_bigint(&120).unwrap(), - &ToBigInt::to_bigint(&23).unwrap() - ) - ); - assert_eq!( - ( - ToBigInt::to_bigint(&2).unwrap(), - ToBigInt::to_bigint(&2).unwrap(), - ToBigInt::to_bigint(&-11).unwrap() - ), - extended_euclid( - &ToBigInt::to_bigint(&122).unwrap(), - &ToBigInt::to_bigint(&22).unwrap() - ) - ); - assert_eq!( - ( - ToBigInt::to_bigint(&2).unwrap(), - ToBigInt::to_bigint(&-9).unwrap(), - ToBigInt::to_bigint(&47).unwrap() - ), - extended_euclid( - &ToBigInt::to_bigint(&240).unwrap(), - &ToBigInt::to_bigint(&46).unwrap() - ) - ); - let (b, s, _) = extended_euclid(&ToBigInt::to_bigint(&253).unwrap(), &*P); - assert_eq!(b, BigInt::one()); - let s_field = FieldPrime { - value: &s - s.div_floor(&*P) * &*P, - }; - assert_eq!( - FieldPrime::from( - "12717674712096337777352654721552646000065650461901806515903699665717959876900" - ), - s_field - ); - } - #[cfg(feature = "bellman")] mod bellman { use super::*; diff --git a/zokrates_field/src/bw6_761.rs b/zokrates_field/src/bw6_761.rs index ef050191..82a90600 100644 --- a/zokrates_field/src/bw6_761.rs +++ b/zokrates_field/src/bw6_761.rs @@ -1,9 +1,5 @@ -prime_field!( - b"258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177", - "bw6_761" -); - -#[cfg(feature = "ark")] use ark_bw6_761::BW6_761; -#[cfg(feature = "ark")] + +prime_field!("bw6_761", BW6_761); + ark_extensions!(BW6_761); diff --git a/zokrates_field/src/lib.rs b/zokrates_field/src/lib.rs index 15536626..fa93ffe3 100644 --- a/zokrates_field/src/lib.rs +++ b/zokrates_field/src/lib.rs @@ -6,9 +6,6 @@ extern crate num_bigint; -#[cfg(feature = "ark")] -use ark_ec::PairingEngine; - #[cfg(feature = "bellman")] use bellman_ce::pairing::{ff::ScalarEngine, Engine}; @@ -36,10 +33,9 @@ pub trait BellmanFieldExtensions { fn new_fq2(c0: &str, c1: &str) -> ::Fqe; } -#[cfg(feature = "ark")] pub trait ArkFieldExtensions { /// An associated type to be able to operate with ark ff traits - type ArkEngine: PairingEngine; + type ArkEngine: ark_ec::PairingEngine; fn from_ark(e: ::Fr) -> Self; fn into_ark(self) -> ::Fr; @@ -159,35 +155,44 @@ pub trait Field: #[macro_use] mod prime_field { macro_rules! prime_field { - ($modulus:expr, $name:expr) => { + ($name:expr, $v:ty) => { use crate::{Field, FieldParseError, Pow}; - use lazy_static::lazy_static; - use num_bigint::{BigInt, BigUint, Sign, ToBigInt}; - use num_integer::Integer; + use ark_ff::{Field as ArkField, PrimeField}; + use num_bigint::BigUint; use num_traits::{CheckedDiv, One, Zero}; - use serde_derive::{Deserialize, Serialize}; + use serde::de::{self, Visitor}; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::convert::From; use std::convert::TryFrom; use std::fmt; use std::fmt::{Debug, Display}; use std::ops::{Add, Div, Mul, Sub}; - lazy_static! { - static ref P: BigInt = BigInt::parse_bytes($modulus, 10).unwrap(); - } + type Fr = <$v as ark_ec::PairingEngine>::Fr; - #[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash, Serialize, Deserialize)] + #[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash)] pub struct FieldPrime { - value: BigInt, + v: Fr, } impl Field for FieldPrime { fn bits(&self) -> u32 { - self.value.bits() as u32 + use ark_ff::BigInteger; + let bits = self.v.into_repr().to_bits_be(); + let mut size = bits.len(); + for bit in bits { + if !bit { + size -= 1; + } else { + break; + } + } + std::cmp::max(size as u32, 1) } fn to_biguint(&self) -> BigUint { - self.value.to_biguint().unwrap() + use ark_ff::BigInteger; + BigUint::from_bytes_le(&self.v.into_repr().to_bytes_le()) } fn to_bits_be(&self) -> Vec { @@ -195,78 +200,72 @@ mod prime_field { } fn to_byte_vector(&self) -> Vec { - match self.value.to_biguint() { - Option::Some(val) => val.to_bytes_le(), - Option::None => panic!("Should never happen."), - } + use ark_ff::BigInteger; + self.v.into_repr().to_bytes_le() } fn from_byte_vector(bytes: Vec) -> Self { - let uval = BigUint::from_bytes_le(bytes.as_slice()); + use ark_ff::FromBytes; + FieldPrime { - value: BigInt::from_biguint(Sign::Plus, uval), + v: Fr::from(::BigInt::read(&bytes[..]).unwrap()), } } fn to_dec_string(&self) -> String { - self.value.to_str_radix(10) + self.to_string() } - fn inverse_mul(&self) -> Option { - let (b, s, _) = extended_euclid(&self.value, &*P); - if b == BigInt::one() { - Some(FieldPrime { - value: &s - s.div_floor(&*P) * &*P, - }) - } else { - None - } + fn inverse_mul(&self) -> Option { + use ark_ff::Field; + Some(FieldPrime { + v: self.v.inverse()?, + }) } + fn min_value() -> FieldPrime { - FieldPrime { - value: ToBigInt::to_bigint(&0).unwrap(), - } + FieldPrime { v: Fr::zero() } } fn max_value() -> FieldPrime { - FieldPrime { - value: &*P - ToBigInt::to_bigint(&1).unwrap(), - } + FieldPrime { v: -Fr::one() } } fn max_unique_value() -> FieldPrime { - use num_traits::Pow; - FieldPrime { - value: BigInt::from(2u32).pow(Self::get_required_bits() - 1) - 1, + v: Fr::from(2u32).pow([Self::get_required_bits() as u64 - 1]) - Fr::one(), } } fn get_required_bits() -> usize { - (*P).bits() + use ark_ff::FpParameters; + ::Params::MODULUS_BITS as usize } fn try_from_dec_str(s: &str) -> Result { - Self::try_from_str(s, 10) - } - fn try_from_str(s: &str, radix: u32) -> Result { - let x = BigInt::parse_bytes(s.as_bytes(), radix).ok_or(FieldParseError)?; + use std::str::FromStr; + Ok(FieldPrime { - value: &x - x.div_floor(&*P) * &*P, + v: Fr::from_str(s).map_err(|_| FieldParseError)?, }) } + fn try_from_str(s: &str, radix: u32) -> Result { + let x = BigUint::parse_bytes(s.as_bytes(), radix).ok_or(FieldParseError)?; + FieldPrime::try_from(x).map_err(|_| FieldParseError) + } fn to_compact_dec_string(&self) -> String { - // values up to (p-1)/2 included are represented as positive, values between (p+1)/2 and p-1 as represented as negative by subtracting p - if self.value <= FieldPrime::max_value().value / 2 { - format!("{}", self.value.to_str_radix(10)) + //values up to (p-1)/2 included are represented as positive, values between (p+1)/2 and p-1 as represented as negative by subtracting p + if self.v.into_repr() <= Fr::modulus_minus_one_div_two() { + format!("{}", self.to_string()) } else { format!( - "({})", - (&self.value - (FieldPrime::max_value().value + BigInt::one())) - .to_str_radix(10) + "(-{})", + (FieldPrime::max_value() - self + FieldPrime::one()).to_string() ) } } fn id() -> [u8; 4] { let mut res = [0u8; 4]; + use ark_ff::BigInteger; + use ark_ff::FpParameters; use sha2::{Digest, Sha256}; - let hash = Sha256::digest(&P.to_bytes_le().1); + let hash = Sha256::digest(&::Params::MODULUS.to_bytes_le()); for i in 0..4 { res[i] = hash[i]; } @@ -280,29 +279,32 @@ mod prime_field { impl Default for FieldPrime { fn default() -> Self { - FieldPrime { - value: BigInt::default(), - } + FieldPrime { v: Fr::zero() } } } impl Display for FieldPrime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.value.to_str_radix(10)) + write!(f, "{}", self.to_biguint()) } } impl Debug for FieldPrime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.value.to_str_radix(10)) + write!(f, "{}", self.to_biguint()) } } impl From for FieldPrime { fn from(num: i32) -> Self { - let x = ToBigInt::to_bigint(&num).unwrap(); - FieldPrime { - value: &x - x.div_floor(&*P) * &*P, + if num < 0 { + FieldPrime { + v: -Fr::from((-num) as u32), + } + } else { + FieldPrime { + v: Fr::from(num as u32), + } } } } @@ -318,28 +320,21 @@ mod prime_field { impl From for FieldPrime { fn from(num: u32) -> Self { - let x = ToBigInt::to_bigint(&num).unwrap(); - FieldPrime { - value: &x - x.div_floor(&*P) * &*P, - } + FieldPrime { v: Fr::from(num) } } } impl From for FieldPrime { fn from(num: usize) -> Self { - let x = ToBigInt::to_bigint(&num).unwrap(); FieldPrime { - value: &x - x.div_floor(&*P) * &*P, + v: Fr::from(num as u128), } } } impl From for FieldPrime { fn from(num: u128) -> Self { - let x = ToBigInt::to_bigint(&num).unwrap(); - FieldPrime { - value: &x - x.div_floor(&*P) * &*P, - } + FieldPrime { v: Fr::from(num) } } } @@ -349,8 +344,10 @@ mod prime_field { fn try_from(value: BigUint) -> Result { match value <= Self::max_value().to_biguint() { true => { - let x = ToBigInt::to_bigint(&value).unwrap(); - Ok(FieldPrime { value: x }) + use std::str::FromStr; + Ok(FieldPrime { + v: Fr::from_str(&value.to_string()).unwrap(), + }) } false => Err(()), } @@ -359,20 +356,16 @@ mod prime_field { impl Zero for FieldPrime { fn zero() -> FieldPrime { - FieldPrime { - value: ToBigInt::to_bigint(&0).unwrap(), - } + FieldPrime { v: Fr::zero() } } fn is_zero(&self) -> bool { - self.value == ToBigInt::to_bigint(&0).unwrap() + self.v.is_zero() } } impl One for FieldPrime { fn one() -> FieldPrime { - FieldPrime { - value: ToBigInt::to_bigint(&1).unwrap(), - } + FieldPrime { v: Fr::one() } } } @@ -380,16 +373,8 @@ mod prime_field { type Output = FieldPrime; fn add(self, other: FieldPrime) -> FieldPrime { - if self.value == BigInt::zero() { - return other; - } - - if other.value == BigInt::zero() { - return self; - } - FieldPrime { - value: (self.value + other.value) % &*P, + v: self.v + other.v, } } } @@ -398,16 +383,8 @@ mod prime_field { type Output = FieldPrime; fn add(self, other: &FieldPrime) -> FieldPrime { - if self.value == BigInt::zero() { - return other.clone(); - } - - if other.value == BigInt::zero() { - return self; - } - FieldPrime { - value: (self.value + &other.value) % &*P, + v: self.v + other.v, } } } @@ -416,9 +393,8 @@ mod prime_field { type Output = FieldPrime; fn sub(self, other: FieldPrime) -> FieldPrime { - let x = self.value - other.value; FieldPrime { - value: &x - x.div_floor(&*P) * &*P, + v: self.v - other.v, } } } @@ -427,9 +403,8 @@ mod prime_field { type Output = FieldPrime; fn sub(self, other: &FieldPrime) -> FieldPrime { - let x = self.value - &other.value; FieldPrime { - value: &x - x.div_floor(&*P) * &*P, + v: self.v - other.v, } } } @@ -438,16 +413,8 @@ mod prime_field { type Output = FieldPrime; fn mul(self, other: FieldPrime) -> FieldPrime { - if self.value == BigInt::one() { - return other; - } - - if other.value == BigInt::one() { - return self; - } - FieldPrime { - value: (self.value * other.value) % &*P, + v: self.v * other.v, } } } @@ -456,23 +423,21 @@ mod prime_field { type Output = FieldPrime; fn mul(self, other: &FieldPrime) -> FieldPrime { - if self.value == BigInt::one() { - return other.clone(); - } - - if other.value == BigInt::one() { - return self; - } - FieldPrime { - value: (self.value * &other.value) % &*P, + v: self.v * other.v, } } } impl CheckedDiv for FieldPrime { fn checked_div(&self, other: &FieldPrime) -> Option { - other.inverse_mul().map(|inv| inv * self) + if other.v == Fr::zero() { + None + } else { + Some(FieldPrime { + v: self.v / other.v, + }) + } } } @@ -496,11 +461,9 @@ mod prime_field { type Output = FieldPrime; fn pow(self, exp: usize) -> FieldPrime { - let mut res = FieldPrime::from(1); - for _ in 0..exp { - res = res * &self; + FieldPrime { + v: self.v.pow(&[exp as u64]), } - res } } @@ -511,12 +474,16 @@ mod prime_field { assert!(self <= &bound); assert!(other <= &bound); - let big_res = &self.value + &other.value; + let left = self.to_biguint(); + let right = other.to_biguint(); - if big_res > bound.value { + let big_res = left + right; + + // we only go up to 2**(bitwidth - 1) because after that we lose uniqueness of bit decomposition + if big_res > bound.to_biguint() { None } else { - Some(FieldPrime { value: big_res }) + Some(self.clone() + other) } } } @@ -528,40 +495,84 @@ mod prime_field { assert!(self <= &bound); assert!(other <= &bound); - let big_res = &self.value * &other.value; + let left = self.to_biguint(); + let right = other.to_biguint(); + + let big_res = left * right; // we only go up to 2**(bitwidth - 1) because after that we lose uniqueness of bit decomposition - if big_res > bound.value { + if big_res > bound.to_biguint() { None } else { - Some(FieldPrime { value: big_res }) + Some(self.clone() * other) } } } - /// Calculates the gcd using an iterative implementation of the extended euclidian algorithm. - /// Returning `(d, s, t)` so that `d = s * a + t * b` - /// - /// # Arguments - /// * `a` - First number as `BigInt` - /// * `b` - Second number as `BigInt` - fn extended_euclid(a: &BigInt, b: &BigInt) -> (BigInt, BigInt, BigInt) { - let (mut s, mut old_s) = (BigInt::zero(), BigInt::one()); - let (mut t, mut old_t) = (BigInt::one(), BigInt::zero()); - let (mut r, mut old_r) = (b.clone(), a.clone()); - while !&r.is_zero() { - let quotient = &old_r / &r; - let tmp_r = old_r.clone(); - old_r = r.clone(); - r = &tmp_r - "ient * &r; - let tmp_s = old_s.clone(); - old_s = s.clone(); - s = &tmp_s - "ient * &s; - let tmp_t = old_t.clone(); - old_t = t.clone(); - t = &tmp_t - "ient * &t; + impl Serialize for FieldPrime { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + use ark_serialize::CanonicalSerialize; + use serde::ser::Error; + let mut data: Vec = vec![]; + self.v + .serialize(&mut data) + .map_err(|e| S::Error::custom(e.to_string()))?; + serializer.serialize_bytes(&data) + } + } + + struct FieldVisitor; + + use serde::de::SeqAccess; + + impl<'de> Visitor<'de> for FieldVisitor { + type Value = FieldPrime; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an ark field element") + } + + fn visit_bytes(self, value: &[u8]) -> Result + where + E: de::Error, + { + use ark_serialize::CanonicalDeserialize; + let value: Fr = Fr::deserialize(value).map_err(|e| E::custom(e.to_string()))?; + + Ok(FieldPrime { v: value }) + } + + fn visit_byte_buf(self, value: Vec) -> Result + where + E: de::Error, + { + self.visit_bytes(&value[..]) + } + + fn visit_seq(self, value: A) -> Result + where + A: SeqAccess<'de>, + { + let mut value = value; + let mut elements = vec![]; + while let Some(v) = value.next_element()? { + elements.push(v); + } + + self.visit_bytes(&elements[..]) + } + } + + impl<'de> Deserialize<'de> for FieldPrime { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_bytes(FieldVisitor) } - return (old_r, old_s, old_t); } }; } @@ -601,7 +612,6 @@ mod prime_field { }; } - #[cfg(feature = "ark")] macro_rules! ark_extensions { ($ark_type:ty) => { use crate::ArkFieldExtensions; @@ -610,16 +620,11 @@ mod prime_field { type ArkEngine = $ark_type; fn from_ark(e: ::Fr) -> Self { - use ark_ff::{BigInteger, PrimeField}; - let mut res: Vec = vec![]; - e.into_repr().write_le(&mut res).unwrap(); - Self::from_byte_vector(res) + Self { v: e } } fn into_ark(self) -> ::Fr { - use core::str::FromStr; - let s = self.to_dec_string(); - ::Fr::from_str(&s).unwrap() + self.v } } }; diff --git a/zokrates_js/Cargo.lock b/zokrates_js/Cargo.lock index 880be408..a2796259 100644 --- a/zokrates_js/Cargo.lock +++ b/zokrates_js/Cargo.lock @@ -49,6 +49,28 @@ dependencies = [ "ark-std", ] +[[package]] +name = "ark-bls12-381" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e1c2ad76c4f725520440b981df3ce2d635f2baa1122750c757c0cf0f3d4b74" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-bn254" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ead066869de5e8cb2938123204d1572f09496b629e146a6f80fa8ec508446ba" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + [[package]] name = "ark-bw6-761" version = "0.2.0" @@ -1571,7 +1593,7 @@ version = "0.1.0" [[package]] name = "zokrates_core" -version = "0.6.7" +version = "0.6.8" dependencies = [ "bellman_ce", "cfg-if 0.1.10", @@ -1600,7 +1622,7 @@ dependencies = [ [[package]] name = "zokrates_embed" -version = "0.1.4" +version = "0.1.5" dependencies = [ "ark-bls12-377", "ark-bw6-761", @@ -1620,6 +1642,13 @@ dependencies = [ name = "zokrates_field" version = "0.4.0" dependencies = [ + "ark-bls12-377", + "ark-bls12-381", + "ark-bn254", + "ark-bw6-761", + "ark-ec", + "ark-ff", + "ark-serialize", "bellman_ce", "bincode", "lazy_static", @@ -1634,7 +1663,7 @@ dependencies = [ [[package]] name = "zokrates_js" -version = "1.0.36" +version = "1.0.37" dependencies = [ "console_error_panic_hook", "js-sys", @@ -1650,7 +1679,7 @@ dependencies = [ [[package]] name = "zokrates_parser" -version = "0.2.4" +version = "0.2.5" dependencies = [ "pest", "pest_derive", @@ -1658,7 +1687,7 @@ dependencies = [ [[package]] name = "zokrates_pest_ast" -version = "0.2.3" +version = "0.2.4" dependencies = [ "from-pest", "lazy_static", diff --git a/zokrates_js/Cargo.toml b/zokrates_js/Cargo.toml index 242d17c5..1ac69837 100644 --- a/zokrates_js/Cargo.toml +++ b/zokrates_js/Cargo.toml @@ -15,6 +15,6 @@ wasm-bindgen = { version = "0.2.46", features = ["serde-serialize"] } typed-arena = "1.4.1" zokrates_core = { path = "../zokrates_core", features = ["wasm", "bellman"], default-features = false } zokrates_common = { path = "../zokrates_common" } -zokrates_field = { path = "../zokrates_field", default-features = false, features = ["bellman"] } +zokrates_field = { path = "../zokrates_field", features = ["bellman"] } zokrates_abi = { path = "../zokrates_abi" } console_error_panic_hook = "0.1.6" \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcFeistel.json b/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcFeistel.json index 6c6f7c65..a362cf0f 100644 --- a/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcFeistel.json +++ b/zokrates_stdlib/tests/tests/hashes/mimcSponge/mimcFeistel.json @@ -24,18 +24,6 @@ ] } } - }, - { - "input": { - "values": ["21888242871839275222246405745257275088548364400416034343698204186575808495617", "0", "0"] - }, - "output": { - "Ok": { - "values": [ - "14543742788565021628577424853847564376151732847602780516906950225481254681152", "21165881269406212375659499083070944693027168220143204011932538650149052385959" - ] - } - } } ] }