Browse Source

moves cmp to be under FpGadget

master
Kobi Gurkan 4 years ago
committed by Pratyush Mishra
parent
commit
8cd0999431
3 changed files with 64 additions and 71 deletions
  1. +61
    -68
      r1cs-std/src/fields/fp/cmp.rs
  2. +3
    -1
      r1cs-std/src/fields/fp/mod.rs
  3. +0
    -2
      r1cs-std/src/lib.rs

r1cs-std/src/cmp.rs → r1cs-std/src/fields/fp/cmp.rs

@ -7,18 +7,14 @@ use algebra::PrimeField;
use core::{cmp::Ordering, marker::PhantomData}; use core::{cmp::Ordering, marker::PhantomData};
use r1cs_core::{ConstraintSystem, SynthesisError}; use r1cs_core::{ConstraintSystem, SynthesisError};
pub struct CmpGadget<ConstraintF: PrimeField> {
constraint_field_type: PhantomData<ConstraintF>,
}
impl<ConstraintF: PrimeField> CmpGadget<ConstraintF> {
fn process_cmp_inputs<CS: ConstraintSystem<ConstraintF>>(
impl<F: PrimeField> FpGadget<F> {
fn process_cmp_inputs<CS: ConstraintSystem<F>>(
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
b: &FpGadget<ConstraintF>,
a: &FpGadget<F>,
b: &FpGadget<F>,
ordering: Ordering, ordering: Ordering,
should_also_check_equality: bool, should_also_check_equality: bool,
) -> Result<(FpGadget<ConstraintF>, FpGadget<ConstraintF>), SynthesisError> {
) -> Result<(FpGadget<F>, FpGadget<F>), SynthesisError> {
let left; let left;
let right; let right;
match ordering { match ordering {
@ -35,7 +31,7 @@ impl CmpGadget {
}, },
}; };
let right_for_check = if should_also_check_equality { let right_for_check = if should_also_check_equality {
right.add_constant(cs.ns(|| "plus one"), &ConstraintF::one())?
right.add_constant(cs.ns(|| "plus one"), &F::one())?
} else { } else {
right.clone() right.clone()
}; };
@ -43,31 +39,31 @@ impl CmpGadget {
Ok((left.clone(), right_for_check)) Ok((left.clone(), right_for_check))
} }
fn check_smaller_than_mod_minus_one_div_two<CS: ConstraintSystem<ConstraintF>>(
fn check_smaller_than_mod_minus_one_div_two<CS: ConstraintSystem<F>>(
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
a: &FpGadget<F>,
) -> Result<(), SynthesisError> { ) -> Result<(), SynthesisError> {
let a_bits = a.to_bits(cs.ns(|| "a to bits"))?; let a_bits = a.to_bits(cs.ns(|| "a to bits"))?;
Boolean::enforce_smaller_or_equal_than::<_, _, ConstraintF, _>(
Boolean::enforce_smaller_or_equal_than::<_, _, F, _>(
cs.ns(|| "enforce smaller than modulus minus one div two"), cs.ns(|| "enforce smaller than modulus minus one div two"),
&a_bits, &a_bits,
ConstraintF::modulus_minus_one_div_two(),
F::modulus_minus_one_div_two(),
)?; )?;
Ok(()) Ok(())
} }
/// this function verifies a and b are <= (p-1)/2 /// this function verifies a and b are <= (p-1)/2
pub fn enforce_cmp<CS: ConstraintSystem<ConstraintF>>(
pub fn enforce_cmp<CS: ConstraintSystem<F>>(
&self,
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
b: &FpGadget<ConstraintF>,
b: &FpGadget<F>,
ordering: Ordering, ordering: Ordering,
should_also_check_equality: bool, should_also_check_equality: bool,
) -> Result<(), SynthesisError> { ) -> Result<(), SynthesisError> {
let (left, right) = Self::process_cmp_inputs( let (left, right) = Self::process_cmp_inputs(
cs.ns(|| "process cmp inputs"), cs.ns(|| "process cmp inputs"),
a,
&self,
b, b,
ordering, ordering,
should_also_check_equality, should_also_check_equality,
@ -76,16 +72,16 @@ impl CmpGadget {
} }
/// this function assumes a and b are known to be <= (p-1)/2 /// this function assumes a and b are known to be <= (p-1)/2
pub fn enforce_cmp_unchecked<CS: ConstraintSystem<ConstraintF>>(
pub fn enforce_cmp_unchecked<CS: ConstraintSystem<F>>(
&self,
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
b: &FpGadget<ConstraintF>,
b: &FpGadget<F>,
ordering: Ordering, ordering: Ordering,
should_also_check_equality: bool, should_also_check_equality: bool,
) -> Result<(), SynthesisError> { ) -> Result<(), SynthesisError> {
let (left, right) = Self::process_cmp_inputs( let (left, right) = Self::process_cmp_inputs(
cs.ns(|| "process cmp inputs"), cs.ns(|| "process cmp inputs"),
a,
&self,
b, b,
ordering, ordering,
should_also_check_equality, should_also_check_equality,
@ -94,16 +90,16 @@ impl CmpGadget {
} }
/// this function verifies a and b are <= (p-1)/2 /// this function verifies a and b are <= (p-1)/2
pub fn is_cmp<CS: ConstraintSystem<ConstraintF>>(
pub fn is_cmp<CS: ConstraintSystem<F>>(
&self,
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
b: &FpGadget<ConstraintF>,
b: &FpGadget<F>,
ordering: Ordering, ordering: Ordering,
should_also_check_equality: bool, should_also_check_equality: bool,
) -> Result<Boolean, SynthesisError> { ) -> Result<Boolean, SynthesisError> {
let (left, right) = Self::process_cmp_inputs( let (left, right) = Self::process_cmp_inputs(
cs.ns(|| "process cmp inputs"), cs.ns(|| "process cmp inputs"),
a,
&self,
b, b,
ordering, ordering,
should_also_check_equality, should_also_check_equality,
@ -112,16 +108,16 @@ impl CmpGadget {
} }
/// this function assumes a and b are known to be <= (p-1)/2 /// this function assumes a and b are known to be <= (p-1)/2
pub fn is_cmp_unchecked<CS: ConstraintSystem<ConstraintF>>(
pub fn is_cmp_unchecked<CS: ConstraintSystem<F>>(
&self,
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
b: &FpGadget<ConstraintF>,
b: &FpGadget<F>,
ordering: Ordering, ordering: Ordering,
should_also_check_equality: bool, should_also_check_equality: bool,
) -> Result<Boolean, SynthesisError> { ) -> Result<Boolean, SynthesisError> {
let (left, right) = Self::process_cmp_inputs( let (left, right) = Self::process_cmp_inputs(
cs.ns(|| "process cmp inputs"), cs.ns(|| "process cmp inputs"),
a,
&self,
b, b,
ordering, ordering,
should_also_check_equality, should_also_check_equality,
@ -130,10 +126,10 @@ impl CmpGadget {
} }
/// this function verifies a and b are <= (p-1)/2 /// this function verifies a and b are <= (p-1)/2
fn is_smaller_than<CS: ConstraintSystem<ConstraintF>>(
fn is_smaller_than<CS: ConstraintSystem<F>>(
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
b: &FpGadget<ConstraintF>,
a: &FpGadget<F>,
b: &FpGadget<F>,
) -> Result<Boolean, SynthesisError> { ) -> Result<Boolean, SynthesisError> {
Self::check_smaller_than_mod_minus_one_div_two(cs.ns(|| "check a in range"), a)?; Self::check_smaller_than_mod_minus_one_div_two(cs.ns(|| "check a in range"), a)?;
Self::check_smaller_than_mod_minus_one_div_two(cs.ns(|| "check b in range"), b)?; Self::check_smaller_than_mod_minus_one_div_two(cs.ns(|| "check b in range"), b)?;
@ -141,24 +137,24 @@ impl CmpGadget {
} }
/// this function assumes a and b are known to be <= (p-1)/2 /// this function assumes a and b are known to be <= (p-1)/2
fn is_smaller_than_unchecked<CS: ConstraintSystem<ConstraintF>>(
fn is_smaller_than_unchecked<CS: ConstraintSystem<F>>(
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
b: &FpGadget<ConstraintF>,
a: &FpGadget<F>,
b: &FpGadget<F>,
) -> Result<Boolean, SynthesisError> { ) -> Result<Boolean, SynthesisError> {
let two = ConstraintF::one() + ConstraintF::one();
let two = F::one() + F::one();
let d0 = a.sub(cs.ns(|| "a - b"), b)?; let d0 = a.sub(cs.ns(|| "a - b"), b)?;
let d = d0.mul_by_constant(cs.ns(|| "mul 2"), &two)?; let d = d0.mul_by_constant(cs.ns(|| "mul 2"), &two)?;
let d_bits = d.to_bits_strict(cs.ns(|| "d to bits"))?;
let d_bits = d.to_bits(cs.ns(|| "d to bits"))?;
let d_bits_len = d_bits.len(); let d_bits_len = d_bits.len();
Ok(d_bits[d_bits_len - 1]) Ok(d_bits[d_bits_len - 1])
} }
/// this function verifies a and b are <= (p-1)/2 /// this function verifies a and b are <= (p-1)/2
fn enforce_smaller_than<CS: ConstraintSystem<ConstraintF>>(
fn enforce_smaller_than<CS: ConstraintSystem<F>>(
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
b: &FpGadget<ConstraintF>,
a: &FpGadget<F>,
b: &FpGadget<F>,
) -> Result<(), SynthesisError> { ) -> Result<(), SynthesisError> {
Self::check_smaller_than_mod_minus_one_div_two(cs.ns(|| "check a in range"), a)?; Self::check_smaller_than_mod_minus_one_div_two(cs.ns(|| "check a in range"), a)?;
Self::check_smaller_than_mod_minus_one_div_two(cs.ns(|| "check b in range"), b)?; Self::check_smaller_than_mod_minus_one_div_two(cs.ns(|| "check b in range"), b)?;
@ -166,21 +162,29 @@ impl CmpGadget {
} }
/// this function assumes a and b are known to be <= (p-1)/2 /// this function assumes a and b are known to be <= (p-1)/2
fn enforce_smaller_than_unchecked<CS: ConstraintSystem<ConstraintF>>(
fn enforce_smaller_than_unchecked<CS: ConstraintSystem<F>>(
mut cs: CS, mut cs: CS,
a: &FpGadget<ConstraintF>,
b: &FpGadget<ConstraintF>,
a: &FpGadget<F>,
b: &FpGadget<F>,
) -> Result<(), SynthesisError> { ) -> Result<(), SynthesisError> {
let is_smaller_than = Self::is_smaller_than_unchecked(cs.ns(|| "is smaller than"), a, b)?; let is_smaller_than = Self::is_smaller_than_unchecked(cs.ns(|| "is smaller than"), a, b)?;
cs.enforce( cs.enforce(
|| "enforce smaller than", || "enforce smaller than",
|_| is_smaller_than.lc(CS::one(), ConstraintF::one()),
|lc| lc + (ConstraintF::one(), CS::one()),
|lc| lc + (ConstraintF::one(), CS::one()),
|_| is_smaller_than.lc(CS::one(), F::one()),
|lc| lc + (F::one(), CS::one()),
|lc| lc + (F::one(), CS::one()),
); );
Ok(()) Ok(())
} }
}
pub struct CmpGadget<ConstraintF: PrimeField> {
constraint_field_type: PhantomData<ConstraintF>,
}
impl<ConstraintF: PrimeField> CmpGadget<ConstraintF> {
} }
#[cfg(test)] #[cfg(test)]
@ -189,7 +193,6 @@ mod test {
use rand_xorshift::XorShiftRng; use rand_xorshift::XorShiftRng;
use std::cmp::Ordering; use std::cmp::Ordering;
use super::CmpGadget;
use crate::{ use crate::{
alloc::AllocGadget, fields::fp::FpGadget, test_constraint_system::TestConstraintSystem, alloc::AllocGadget, fields::fp::FpGadget, test_constraint_system::TestConstraintSystem,
}; };
@ -222,17 +225,15 @@ mod test {
match a.cmp(&b) { match a.cmp(&b) {
Ordering::Less => { Ordering::Less => {
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than test"), cs.ns(|| "smaller than test"),
&a_var,
&b_var, &b_var,
Ordering::Less, Ordering::Less,
false, false,
) )
.unwrap(); .unwrap();
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than test 2"), cs.ns(|| "smaller than test 2"),
&a_var,
&b_var, &b_var,
Ordering::Less, Ordering::Less,
true, true,
@ -240,17 +241,15 @@ mod test {
.unwrap(); .unwrap();
}, },
Ordering::Greater => { Ordering::Greater => {
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than test"), cs.ns(|| "smaller than test"),
&a_var,
&b_var, &b_var,
Ordering::Greater, Ordering::Greater,
false, false,
) )
.unwrap(); .unwrap();
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than test 2"), cs.ns(|| "smaller than test 2"),
&a_var,
&b_var, &b_var,
Ordering::Greater, Ordering::Greater,
true, true,
@ -275,17 +274,15 @@ mod test {
match b.cmp(&a) { match b.cmp(&a) {
Ordering::Less => { Ordering::Less => {
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than test"), cs.ns(|| "smaller than test"),
&a_var,
&b_var, &b_var,
Ordering::Less, Ordering::Less,
false, false,
) )
.unwrap(); .unwrap();
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than test 2"), cs.ns(|| "smaller than test 2"),
&a_var,
&b_var, &b_var,
Ordering::Less, Ordering::Less,
true, true,
@ -293,17 +290,15 @@ mod test {
.unwrap(); .unwrap();
}, },
Ordering::Greater => { Ordering::Greater => {
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than test"), cs.ns(|| "smaller than test"),
&a_var,
&b_var, &b_var,
Ordering::Greater, Ordering::Greater,
false, false,
) )
.unwrap(); .unwrap();
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than test 2"), cs.ns(|| "smaller than test 2"),
&a_var,
&b_var, &b_var,
Ordering::Greater, Ordering::Greater,
true, true,
@ -320,10 +315,9 @@ mod test {
let mut cs = TestConstraintSystem::<Fr>::new(); let mut cs = TestConstraintSystem::<Fr>::new();
let a = rand_in_range(&mut rng); let a = rand_in_range(&mut rng);
let a_var = FpGadget::<Fr>::alloc(cs.ns(|| "a"), || Ok(a)).unwrap(); let a_var = FpGadget::<Fr>::alloc(cs.ns(|| "a"), || Ok(a)).unwrap();
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than test"), cs.ns(|| "smaller than test"),
&a_var, &a_var,
&a_var,
Ordering::Less, Ordering::Less,
false, false,
) )
@ -336,10 +330,9 @@ mod test {
let mut cs = TestConstraintSystem::<Fr>::new(); let mut cs = TestConstraintSystem::<Fr>::new();
let a = rand_in_range(&mut rng); let a = rand_in_range(&mut rng);
let a_var = FpGadget::<Fr>::alloc(cs.ns(|| "a"), || Ok(a)).unwrap(); let a_var = FpGadget::<Fr>::alloc(cs.ns(|| "a"), || Ok(a)).unwrap();
CmpGadget::<Fr>::enforce_cmp(
a_var.enforce_cmp(
cs.ns(|| "smaller than or equal to test"), cs.ns(|| "smaller than or equal to test"),
&a_var, &a_var,
&a_var,
Ordering::Less, Ordering::Less,
true, true,
) )

r1cs-std/src/fields/fp.rs → r1cs-std/src/fields/fp/mod.rs

@ -9,6 +9,8 @@ use core::borrow::Borrow;
use crate::{boolean::AllocatedBit, prelude::*, Assignment, Vec}; use crate::{boolean::AllocatedBit, prelude::*, Assignment, Vec};
pub mod cmp;
#[derive(Debug)] #[derive(Debug)]
pub struct FpGadget<F: PrimeField> { pub struct FpGadget<F: PrimeField> {
pub value: Option<F>, pub value: Option<F>,
@ -625,4 +627,4 @@ impl AllocGadget for FpGadget {
variable: Var(variable), variable: Var(variable),
}) })
} }
}
}

+ 0
- 2
r1cs-std/src/lib.rs

@ -60,7 +60,6 @@ pub use instantiated::jubjub;
pub mod pairing; pub mod pairing;
pub mod alloc; pub mod alloc;
pub mod cmp;
pub mod eq; pub mod eq;
pub mod select; pub mod select;
@ -68,7 +67,6 @@ pub mod prelude {
pub use crate::{ pub use crate::{
alloc::*, alloc::*,
bits::{boolean::Boolean, uint32::UInt32, uint8::UInt8, ToBitsGadget, ToBytesGadget}, bits::{boolean::Boolean, uint32::UInt32, uint8::UInt8, ToBitsGadget, ToBytesGadget},
cmp::CmpGadget,
eq::*, eq::*,
fields::FieldGadget, fields::FieldGadget,
groups::GroupGadget, groups::GroupGadget,

Loading…
Cancel
Save