|
|
@ -8,52 +8,11 @@ use core::cmp::Ordering; |
|
|
|
use r1cs_core::{ConstraintSystem, SynthesisError};
|
|
|
|
|
|
|
|
impl<F: PrimeField> FpGadget<F> {
|
|
|
|
fn process_cmp_inputs<CS: ConstraintSystem<F>>(
|
|
|
|
mut cs: CS,
|
|
|
|
a: &FpGadget<F>,
|
|
|
|
b: &FpGadget<F>,
|
|
|
|
ordering: Ordering,
|
|
|
|
should_also_check_equality: bool,
|
|
|
|
) -> Result<(FpGadget<F>, FpGadget<F>), SynthesisError> {
|
|
|
|
let left;
|
|
|
|
let right;
|
|
|
|
match ordering {
|
|
|
|
Ordering::Less => {
|
|
|
|
left = a;
|
|
|
|
right = b;
|
|
|
|
},
|
|
|
|
Ordering::Greater => {
|
|
|
|
left = b;
|
|
|
|
right = a;
|
|
|
|
},
|
|
|
|
Ordering::Equal => {
|
|
|
|
return Err(SynthesisError::Unsatisfiable);
|
|
|
|
},
|
|
|
|
};
|
|
|
|
let right_for_check = if should_also_check_equality {
|
|
|
|
right.add_constant(cs.ns(|| "plus one"), &F::one())?
|
|
|
|
} else {
|
|
|
|
right.clone()
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok((left.clone(), right_for_check))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_smaller_than_mod_minus_one_div_two<CS: ConstraintSystem<F>>(
|
|
|
|
mut cs: CS,
|
|
|
|
a: &FpGadget<F>,
|
|
|
|
) -> Result<(), SynthesisError> {
|
|
|
|
let a_bits = a.to_bits(cs.ns(|| "a to bits"))?;
|
|
|
|
Boolean::enforce_smaller_or_equal_than::<_, _, F, _>(
|
|
|
|
cs.ns(|| "enforce smaller than modulus minus one div two"),
|
|
|
|
&a_bits,
|
|
|
|
F::modulus_minus_one_div_two(),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// this function verifies a and b are <= (p-1)/2
|
|
|
|
/// This function enforces the ordering between `self` and `b`. The
|
|
|
|
/// constraint system will not be satisfied otherwise. If `self` should
|
|
|
|
/// also be checked for equality, e.g. `a <= b` instead of `a < b`, set
|
|
|
|
/// `should_also_check_quality` to `true`. This variant verifies `a` and `b`
|
|
|
|
/// are `<= (p-1)/2`.
|
|
|
|
pub fn enforce_cmp<CS: ConstraintSystem<F>>(
|
|
|
|
&self,
|
|
|
|
mut cs: CS,
|
|
|
@ -71,7 +30,11 @@ impl FpGadget { |
|
|
|
Self::enforce_smaller_than_unchecked(cs.ns(|| "enforce smaller than"), &left, &right)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// this function assumes a and b are known to be <= (p-1)/2
|
|
|
|
/// This function enforces the ordering between `self` and `b`. The
|
|
|
|
/// constraint system will not be satisfied otherwise. If `self` should
|
|
|
|
/// also be checked for equality, e.g. `a <= b` instead of `a < b`, set
|
|
|
|
/// `should_also_check_quality` to `true`. This variant assumes `a` and `b`
|
|
|
|
/// are `<= (p-1)/2` and does not generate constraints to verify that.
|
|
|
|
pub fn enforce_cmp_unchecked<CS: ConstraintSystem<F>>(
|
|
|
|
&self,
|
|
|
|
mut cs: CS,
|
|
|
@ -89,7 +52,12 @@ impl FpGadget { |
|
|
|
Self::enforce_smaller_than(cs.ns(|| "enforce smaller than"), &left, &right)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// this function verifies a and b are <= (p-1)/2
|
|
|
|
/// This function checks the ordering between `self` and `b`. It outputs a
|
|
|
|
/// `Boolean` that contains the result - `1` if true, `0` otherwise. The
|
|
|
|
/// constraint system will be satisfied in any case. If `self` should
|
|
|
|
/// also be checked for equality, e.g. `a <= b` instead of `a < b`, set
|
|
|
|
/// `should_also_check_quality` to `true`. This variant verifies `a` and `b`
|
|
|
|
/// are `<= (p-1)/2`.
|
|
|
|
pub fn is_cmp<CS: ConstraintSystem<F>>(
|
|
|
|
&self,
|
|
|
|
mut cs: CS,
|
|
|
@ -107,7 +75,12 @@ impl FpGadget { |
|
|
|
Self::is_smaller_than(cs.ns(|| "enforce smaller than"), &left, &right)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// this function assumes a and b are known to be <= (p-1)/2
|
|
|
|
/// This function checks the ordering between `self` and `b`. It outputs a
|
|
|
|
/// `Boolean` that contains the result - `1` if true, `0` otherwise. The
|
|
|
|
/// constraint system will be satisfied in any case. If `self` should
|
|
|
|
/// also be checked for equality, e.g. `a <= b` instead of `a < b`, set
|
|
|
|
/// `should_also_check_quality` to `true`. This variant assumes `a` and `b`
|
|
|
|
/// are `<= (p-1)/2` and does not generate constraints to verify that.
|
|
|
|
pub fn is_cmp_unchecked<CS: ConstraintSystem<F>>(
|
|
|
|
&self,
|
|
|
|
mut cs: CS,
|
|
|
@ -125,7 +98,54 @@ impl FpGadget { |
|
|
|
Self::is_smaller_than_unchecked(cs.ns(|| "enforce smaller than"), &left, &right)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// this function verifies a and b are <= (p-1)/2
|
|
|
|
fn process_cmp_inputs<CS: ConstraintSystem<F>>(
|
|
|
|
mut cs: CS,
|
|
|
|
a: &FpGadget<F>,
|
|
|
|
b: &FpGadget<F>,
|
|
|
|
ordering: Ordering,
|
|
|
|
should_also_check_equality: bool,
|
|
|
|
) -> Result<(FpGadget<F>, FpGadget<F>), SynthesisError> {
|
|
|
|
let left;
|
|
|
|
let right;
|
|
|
|
match ordering {
|
|
|
|
Ordering::Less => {
|
|
|
|
left = a;
|
|
|
|
right = b;
|
|
|
|
},
|
|
|
|
Ordering::Greater => {
|
|
|
|
left = b;
|
|
|
|
right = a;
|
|
|
|
},
|
|
|
|
Ordering::Equal => {
|
|
|
|
return Err(SynthesisError::Unsatisfiable);
|
|
|
|
},
|
|
|
|
};
|
|
|
|
let right_for_check = if should_also_check_equality {
|
|
|
|
right.add_constant(cs.ns(|| "plus one"), &F::one())?
|
|
|
|
} else {
|
|
|
|
right.clone()
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok((left.clone(), right_for_check))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helper function to enforce `a <= (p-1)/2`.
|
|
|
|
fn check_smaller_than_mod_minus_one_div_two<CS: ConstraintSystem<F>>(
|
|
|
|
mut cs: CS,
|
|
|
|
a: &FpGadget<F>,
|
|
|
|
) -> Result<(), SynthesisError> {
|
|
|
|
let a_bits = a.to_bits(cs.ns(|| "a to bits"))?;
|
|
|
|
Boolean::enforce_smaller_or_equal_than::<_, _, F, _>(
|
|
|
|
cs.ns(|| "enforce smaller than modulus minus one div two"),
|
|
|
|
&a_bits,
|
|
|
|
F::modulus_minus_one_div_two(),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Helper function to check `a < b` and output a result bit. This function
|
|
|
|
/// verifies `a` and `b` are `<= (p-1)/2`.
|
|
|
|
fn is_smaller_than<CS: ConstraintSystem<F>>(
|
|
|
|
mut cs: CS,
|
|
|
|
a: &FpGadget<F>,
|
|
|
@ -136,7 +156,9 @@ impl FpGadget { |
|
|
|
Self::is_smaller_than_unchecked(cs.ns(|| "enforce smaller than"), a, b)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// this function assumes a and b are known to be <= (p-1)/2
|
|
|
|
/// Helper function to check `a < b` and output a result bit. This function
|
|
|
|
/// assumes `a` and `b` are `<= (p-1)/2` and does not generate constraints
|
|
|
|
/// to verify that.
|
|
|
|
fn is_smaller_than_unchecked<CS: ConstraintSystem<F>>(
|
|
|
|
mut cs: CS,
|
|
|
|
a: &FpGadget<F>,
|
|
|
@ -150,7 +172,8 @@ impl FpGadget { |
|
|
|
Ok(d_bits[d_bits_len - 1])
|
|
|
|
}
|
|
|
|
|
|
|
|
/// this function verifies a and b are <= (p-1)/2
|
|
|
|
/// Helper function to enforce `a < b`. This function verifies `a` and `b`
|
|
|
|
/// are `<= (p-1)/2`.
|
|
|
|
fn enforce_smaller_than<CS: ConstraintSystem<F>>(
|
|
|
|
mut cs: CS,
|
|
|
|
a: &FpGadget<F>,
|
|
|
@ -161,7 +184,8 @@ impl FpGadget { |
|
|
|
Self::enforce_smaller_than_unchecked(cs.ns(|| "enforce smaller than"), a, b)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// this function assumes a and b are known to be <= (p-1)/2
|
|
|
|
/// Helper function to enforce `a < b`. This function assumes `a` and `b`
|
|
|
|
/// are `<= (p-1)/2` and does not generate constraints to verify that.
|
|
|
|
fn enforce_smaller_than_unchecked<CS: ConstraintSystem<F>>(
|
|
|
|
mut cs: CS,
|
|
|
|
a: &FpGadget<F>,
|
|
|
|