|
@ -3,7 +3,7 @@ use algebra::{ |
|
|
twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective},
|
|
|
twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective},
|
|
|
AffineCurve, MontgomeryModelParameters, ProjectiveCurve, TEModelParameters,
|
|
|
AffineCurve, MontgomeryModelParameters, ProjectiveCurve, TEModelParameters,
|
|
|
},
|
|
|
},
|
|
|
BigInteger, BitIterator, Field, One, PrimeField, Zero,
|
|
|
|
|
|
|
|
|
BigInteger, BitIteratorBE, Field, One, PrimeField, Zero,
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError};
|
|
|
use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError};
|
|
@ -328,22 +328,12 @@ where |
|
|
fn enforce_prime_order(&self) -> Result<(), SynthesisError> {
|
|
|
fn enforce_prime_order(&self) -> Result<(), SynthesisError> {
|
|
|
let r_minus_1 = (-P::ScalarField::one()).into_repr();
|
|
|
let r_minus_1 = (-P::ScalarField::one()).into_repr();
|
|
|
|
|
|
|
|
|
let mut seen_one = false;
|
|
|
|
|
|
let mut result = Self::zero();
|
|
|
let mut result = Self::zero();
|
|
|
for b in BitIterator::new(r_minus_1) {
|
|
|
|
|
|
let old_seen_one = seen_one;
|
|
|
|
|
|
if seen_one {
|
|
|
|
|
|
result.double_in_place()?;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
seen_one = b;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
for b in BitIteratorBE::without_leading_zeros(r_minus_1) {
|
|
|
|
|
|
result.double_in_place()?;
|
|
|
|
|
|
|
|
|
if b {
|
|
|
if b {
|
|
|
result = if old_seen_one {
|
|
|
|
|
|
result + self
|
|
|
|
|
|
} else {
|
|
|
|
|
|
self.clone()
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
result += self;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
self.negate()?.enforce_equal(&result)?;
|
|
|
self.negate()?.enforce_equal(&result)?;
|
|
@ -398,7 +388,7 @@ where |
|
|
Ok(Self::new(self.x.negate()?, self.y.clone()))
|
|
|
Ok(Self::new(self.x.negate()?, self.y.clone()))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
fn precomputed_base_scalar_mul<'a, I, B>(
|
|
|
|
|
|
|
|
|
fn precomputed_base_scalar_mul_le<'a, I, B>(
|
|
|
&mut self,
|
|
|
&mut self,
|
|
|
scalar_bits_with_base_powers: I,
|
|
|
scalar_bits_with_base_powers: I,
|
|
|
) -> Result<(), SynthesisError>
|
|
|
) -> Result<(), SynthesisError>
|
|
@ -477,7 +467,7 @@ where |
|
|
acc_power += base_power;
|
|
|
acc_power += base_power;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
let bits = bits.borrow().to_bits()?;
|
|
|
|
|
|
|
|
|
let bits = bits.borrow().to_bits_le()?;
|
|
|
if bits.len() != CHUNK_SIZE {
|
|
|
if bits.len() != CHUNK_SIZE {
|
|
|
return Err(SynthesisError::Unsatisfiable);
|
|
|
return Err(SynthesisError::Unsatisfiable);
|
|
|
}
|
|
|
}
|
|
@ -552,10 +542,12 @@ where |
|
|
power_of_2 += 1;
|
|
|
power_of_2 += 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
let cofactor_weight = BitIterator::new(cofactor.as_slice()).filter(|b| *b).count();
|
|
|
|
|
|
|
|
|
let cofactor_weight = BitIteratorBE::new(cofactor.as_slice())
|
|
|
|
|
|
.filter(|b| *b)
|
|
|
|
|
|
.count();
|
|
|
let modulus_minus_1 = (-P::ScalarField::one()).into_repr(); // r - 1
|
|
|
let modulus_minus_1 = (-P::ScalarField::one()).into_repr(); // r - 1
|
|
|
let modulus_minus_1_weight =
|
|
|
let modulus_minus_1_weight =
|
|
|
BitIterator::new(modulus_minus_1).filter(|b| *b).count();
|
|
|
|
|
|
|
|
|
BitIteratorBE::new(modulus_minus_1).filter(|b| *b).count();
|
|
|
|
|
|
|
|
|
// We pick the most efficient method of performing the prime order check:
|
|
|
// We pick the most efficient method of performing the prime order check:
|
|
|
// If the cofactor has lower hamming weight than the scalar field's modulus,
|
|
|
// If the cofactor has lower hamming weight than the scalar field's modulus,
|
|
@ -571,7 +563,10 @@ where |
|
|
|| f().map(|g| g.borrow().into_affine().mul_by_cofactor_inv().into()),
|
|
|
|| f().map(|g| g.borrow().into_affine().mul_by_cofactor_inv().into()),
|
|
|
mode,
|
|
|
mode,
|
|
|
)?;
|
|
|
)?;
|
|
|
(ge, BitIterator::new(cofactor.as_slice()))
|
|
|
|
|
|
|
|
|
(
|
|
|
|
|
|
ge,
|
|
|
|
|
|
BitIteratorBE::without_leading_zeros(cofactor.as_slice()),
|
|
|
|
|
|
)
|
|
|
} else {
|
|
|
} else {
|
|
|
let ge = Self::new_variable_omit_prime_order_check(
|
|
|
let ge = Self::new_variable_omit_prime_order_check(
|
|
|
cs.ns("Witness without subgroup check with `r` check"),
|
|
|
cs.ns("Witness without subgroup check with `r` check"),
|
|
@ -580,37 +575,30 @@ where |
|
|
let g = g.into_affine();
|
|
|
let g = g.into_affine();
|
|
|
let mut power_of_two = P::ScalarField::one().into_repr();
|
|
|
let mut power_of_two = P::ScalarField::one().into_repr();
|
|
|
power_of_two.muln(power_of_2);
|
|
|
power_of_two.muln(power_of_2);
|
|
|
let power_of_two_inv =
|
|
|
|
|
|
P::ScalarField::from(power_of_two).inverse().unwrap();
|
|
|
|
|
|
|
|
|
let power_of_two_inv = P::ScalarField::from_repr(power_of_two)
|
|
|
|
|
|
.and_then(|n| n.inverse())
|
|
|
|
|
|
.unwrap();
|
|
|
g.mul(power_of_two_inv)
|
|
|
g.mul(power_of_two_inv)
|
|
|
})
|
|
|
})
|
|
|
},
|
|
|
},
|
|
|
mode,
|
|
|
mode,
|
|
|
)?;
|
|
|
)?;
|
|
|
|
|
|
|
|
|
(ge, BitIterator::new(modulus_minus_1.as_ref()))
|
|
|
|
|
|
|
|
|
(
|
|
|
|
|
|
ge,
|
|
|
|
|
|
BitIteratorBE::without_leading_zeros(modulus_minus_1.as_ref()),
|
|
|
|
|
|
)
|
|
|
};
|
|
|
};
|
|
|
// Remove the even part of the cofactor
|
|
|
// Remove the even part of the cofactor
|
|
|
for _ in 0..power_of_2 {
|
|
|
for _ in 0..power_of_2 {
|
|
|
ge.double_in_place()?;
|
|
|
ge.double_in_place()?;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
let mut seen_one = false;
|
|
|
|
|
|
let mut result = Self::zero();
|
|
|
let mut result = Self::zero();
|
|
|
for b in iter {
|
|
|
for b in iter {
|
|
|
let old_seen_one = seen_one;
|
|
|
|
|
|
if seen_one {
|
|
|
|
|
|
result.double_in_place()?;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
seen_one = b;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.double_in_place()?;
|
|
|
if b {
|
|
|
if b {
|
|
|
result = if old_seen_one {
|
|
|
|
|
|
result + &ge
|
|
|
|
|
|
} else {
|
|
|
|
|
|
ge.clone()
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
result += ≥
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
if cofactor_weight < modulus_minus_1_weight {
|
|
|
if cofactor_weight < modulus_minus_1_weight {
|
|
@ -829,20 +817,20 @@ where |
|
|
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
|
|
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
|
|
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
|
|
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
|
|
{
|
|
|
{
|
|
|
fn to_bits(
|
|
|
|
|
|
|
|
|
fn to_bits_le(
|
|
|
&self,
|
|
|
&self,
|
|
|
) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
|
|
) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
|
|
let mut x_bits = self.x.to_bits()?;
|
|
|
|
|
|
let y_bits = self.y.to_bits()?;
|
|
|
|
|
|
|
|
|
let mut x_bits = self.x.to_bits_le()?;
|
|
|
|
|
|
let y_bits = self.y.to_bits_le()?;
|
|
|
x_bits.extend_from_slice(&y_bits);
|
|
|
x_bits.extend_from_slice(&y_bits);
|
|
|
Ok(x_bits)
|
|
|
Ok(x_bits)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
fn to_non_unique_bits(
|
|
|
|
|
|
|
|
|
fn to_non_unique_bits_le(
|
|
|
&self,
|
|
|
&self,
|
|
|
) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
|
|
) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
|
|
let mut x_bits = self.x.to_non_unique_bits()?;
|
|
|
|
|
|
let y_bits = self.y.to_non_unique_bits()?;
|
|
|
|
|
|
|
|
|
let mut x_bits = self.x.to_non_unique_bits_le()?;
|
|
|
|
|
|
let y_bits = self.y.to_non_unique_bits_le()?;
|
|
|
x_bits.extend_from_slice(&y_bits);
|
|
|
x_bits.extend_from_slice(&y_bits);
|
|
|
|
|
|
|
|
|
Ok(x_bits)
|
|
|
Ok(x_bits)
|
|
@ -884,7 +872,7 @@ where |
|
|
for<'a> &'a GG: GroupOpsBounds<'a, TEProjective<P>, GG>,
|
|
|
for<'a> &'a GG: GroupOpsBounds<'a, TEProjective<P>, GG>,
|
|
|
{
|
|
|
{
|
|
|
use crate::prelude::*;
|
|
|
use crate::prelude::*;
|
|
|
use algebra::{test_rng, Group, UniformRand};
|
|
|
|
|
|
|
|
|
use algebra::{test_rng, BitIteratorLE, Group, UniformRand};
|
|
|
use r1cs_core::ConstraintSystem;
|
|
|
use r1cs_core::ConstraintSystem;
|
|
|
|
|
|
|
|
|
crate::groups::test::group_test::<TEProjective<P>, _, GG>()?;
|
|
|
crate::groups::test::group_test::<TEProjective<P>, _, GG>()?;
|
|
@ -944,11 +932,9 @@ where |
|
|
let native_result = AffineCurve::mul(&aa.into_affine(), scalar);
|
|
|
let native_result = AffineCurve::mul(&aa.into_affine(), scalar);
|
|
|
let native_result = native_result.into_affine();
|
|
|
let native_result = native_result.into_affine();
|
|
|
|
|
|
|
|
|
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
|
|
|
|
|
|
// Get the scalar bits into little-endian form.
|
|
|
|
|
|
scalar.reverse();
|
|
|
|
|
|
|
|
|
let scalar: Vec<bool> = BitIteratorLE::new(scalar.into_repr()).collect();
|
|
|
let input: Vec<Boolean<_>> = Vec::new_witness(cs.ns("bits"), || Ok(scalar)).unwrap();
|
|
|
let input: Vec<Boolean<_>> = Vec::new_witness(cs.ns("bits"), || Ok(scalar)).unwrap();
|
|
|
let result = gadget_a.mul_bits(input.iter())?;
|
|
|
|
|
|
|
|
|
let result = gadget_a.scalar_mul_le(input.iter())?;
|
|
|
let result_val = result.value()?.into_affine();
|
|
|
let result_val = result.value()?.into_affine();
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
result_val, native_result,
|
|
|
result_val, native_result,
|
|
|