Refactor bit iteration infrastructure:

* `to_bits` -> `to_bits_le`
* `BitIterator` -> `BitIteratorLE` + `BitIteratorBE`
* `found_one`/`seen_one` -> `BitIteratorBE::without_leading_zeros`
This commit is contained in:
Pratyush Mishra
2020-08-28 11:39:38 -07:00
parent bce788419f
commit 6cca9327be
31 changed files with 398 additions and 455 deletions

View File

@@ -31,7 +31,7 @@ impl<F: PrimeField> CommitmentGadget<blake2s::Commitment, F> for CommGadget {
) -> Result<Self::OutputVar, SynthesisError> {
let mut input_bits = Vec::with_capacity(512);
for byte in input.iter().chain(r.0.iter()) {
input_bits.extend_from_slice(&byte.into_bits_le());
input_bits.extend_from_slice(&byte.to_bits_le()?);
}
let mut result = Vec::new();
for int in evaluate_blake2s(&input_bits)?.into_iter() {

View File

@@ -5,7 +5,7 @@ use crate::{
};
use algebra_core::{
fields::{Field, PrimeField},
to_bytes, ProjectiveCurve, ToBytes, Zero,
to_bytes, ProjectiveCurve, Zero,
};
use r1cs_core::{Namespace, SynthesisError};
@@ -73,17 +73,20 @@ where
assert_eq!(parameters.params.generators.len(), W::NUM_WINDOWS);
// Allocate new variable for commitment output.
let input_in_bits: Vec<_> = padded_input
let input_in_bits: Vec<Boolean<_>> = padded_input
.iter()
.flat_map(|byte| byte.into_bits_le())
.flat_map(|byte| byte.to_bits_le().unwrap())
.collect();
let input_in_bits = input_in_bits.chunks(W::WINDOW_SIZE);
let mut result =
GG::precomputed_base_multiscalar_mul(&parameters.params.generators, input_in_bits)?;
GG::precomputed_base_multiscalar_mul_le(&parameters.params.generators, input_in_bits)?;
// Compute h^r
let rand_bits: Vec<_> = r.0.iter().flat_map(|byte| byte.into_bits_le()).collect();
result.precomputed_base_scalar_mul(
let rand_bits: Vec<_> =
r.0.iter()
.flat_map(|byte| byte.to_bits_le().unwrap())
.collect();
result.precomputed_base_scalar_mul_le(
rand_bits
.iter()
.zip(&parameters.params.randomness_generator),

View File

@@ -2,7 +2,8 @@ use crate::{Error, Vec};
use algebra_core::{
bytes::ToBytes,
io::{Result as IoResult, Write},
BitIterator, Field, FpParameters, PrimeField, ProjectiveCurve, ToConstraintField, UniformRand,
BitIteratorLE, Field, FpParameters, PrimeField, ProjectiveCurve, ToConstraintField,
UniformRand,
};
use core::marker::PhantomData;
@@ -99,9 +100,7 @@ impl<C: ProjectiveCurve, W: Window> CommitmentScheme for Commitment<C, W> {
let randomize_time = start_timer!(|| "Randomize");
// Compute h^r.
let mut scalar_bits = BitIterator::new(randomness.0.into_repr()).collect::<Vec<_>>();
scalar_bits.reverse();
for (bit, power) in scalar_bits
for (bit, power) in BitIteratorLE::new(randomness.0.into_repr())
.into_iter()
.zip(&parameters.randomness_generator)
{

View File

@@ -56,7 +56,10 @@ where
input: &[UInt8<ConstraintF<P>>],
) -> Result<Self::OutputVar, SynthesisError> {
// Pad the input if it is not the current length.
let mut input_in_bits: Vec<_> = input.iter().flat_map(|byte| byte.into_bits_le()).collect();
let mut input_in_bits: Vec<Boolean<_>> = input
.iter()
.flat_map(|byte| byte.to_bits_le().unwrap())
.collect();
if (input_in_bits.len()) % CHUNK_SIZE != 0 {
let current_length = input_in_bits.len();
for _ in 0..(CHUNK_SIZE - current_length % CHUNK_SIZE) {

View File

@@ -190,7 +190,8 @@ mod test {
let rng = &mut test_rng();
let params = <CRH<EdwardsParameters, TestWindow> as FixedLengthCRH>::setup(rng).unwrap();
<CRH<EdwardsParameters, TestWindow> as FixedLengthCRH>::evaluate(&params, &[1, 2, 3])
.unwrap();
let _ =
<CRH<EdwardsParameters, TestWindow> as FixedLengthCRH>::evaluate(&params, &[1, 2, 3])
.unwrap();
}
}

View File

@@ -61,11 +61,13 @@ where
assert_eq!(parameters.params.generators.len(), W::NUM_WINDOWS);
// Allocate new variable for the result.
let input_in_bits: Vec<_> = padded_input.iter().flat_map(|b| b.into_bits_le()).collect();
let input_in_bits: Vec<Boolean<_>> = padded_input
.iter()
.flat_map(|b| b.to_bits_le().unwrap())
.collect();
let input_in_bits = input_in_bits.chunks(W::WINDOW_SIZE);
let result =
GG::precomputed_base_multiscalar_mul(&parameters.params.generators, input_in_bits)?;
GG::precomputed_base_multiscalar_mul_le(&parameters.params.generators, input_in_bits)?;
Ok(result)
}
}

View File

@@ -37,7 +37,7 @@ pub trait NIZKVerifierGadget<N: NIZK, ConstraintF: Field> {
fn verify<'a, T: 'a + ToBitsGadget<ConstraintF> + ?Sized>(
verification_key: &Self::VerificationKeyVar,
input: impl Iterator<Item = &'a T>,
input: impl IntoIterator<Item = &'a T>,
proof: &Self::ProofVar,
) -> Result<(), SynthesisError> {
Self::conditional_verify(verification_key, input, proof, &Boolean::constant(true))
@@ -45,14 +45,14 @@ pub trait NIZKVerifierGadget<N: NIZK, ConstraintF: Field> {
fn conditional_verify<'a, T: 'a + ToBitsGadget<ConstraintF> + ?Sized>(
verification_key: &Self::VerificationKeyVar,
input: impl Iterator<Item = &'a T>,
input: impl IntoIterator<Item = &'a T>,
proof: &Self::ProofVar,
condition: &Boolean<ConstraintF>,
) -> Result<(), SynthesisError>;
fn conditional_verify_prepared<'a, T: 'a + ToBitsGadget<ConstraintF> + ?Sized>(
prepared_verification_key: &Self::PreparedVerificationKeyVar,
input: impl Iterator<Item = &'a T>,
input: impl IntoIterator<Item = &'a T>,
proof: &Self::ProofVar,
condition: &Boolean<ConstraintF>,
) -> Result<(), SynthesisError>;

View File

@@ -178,7 +178,7 @@ where
fn conditional_verify<'a, T: 'a + ToBitsGadget<E::Fq> + ?Sized>(
vk: &Self::VerificationKeyVar,
input: impl Iterator<Item = &'a T>,
input: impl IntoIterator<Item = &'a T>,
proof: &Self::ProofVar,
condition: &Boolean<E::Fq>,
) -> Result<(), SynthesisError> {
@@ -190,7 +190,7 @@ where
fn conditional_verify_prepared<'a, T: 'a + ToBitsGadget<E::Fq> + ?Sized>(
pvk: &Self::PreparedVerificationKeyVar,
mut input: impl Iterator<Item = &'a T>,
input: impl IntoIterator<Item = &'a T>,
proof: &Self::ProofVar,
condition: &Boolean<E::Fq>,
) -> Result<(), SynthesisError> {
@@ -200,9 +200,10 @@ where
let g_psi = {
let mut g_psi = pvk.query[0].clone();
let mut input_len = 1;
let mut input = input.into_iter();
for (input, b) in input.by_ref().zip(pvk.query.iter().skip(1)) {
let input_bits = input.to_bits()?;
g_psi += b.mul_bits(input_bits.iter())?;
let input_bits = input.to_bits_le()?;
g_psi += b.scalar_mul_le(input_bits.iter())?;
input_len += 1;
}
// Check that the input and the query in the verification are of the
@@ -398,7 +399,7 @@ mod test {
use super::*;
use algebra::{
bls12_377::{Bls12_377, Fq, Fr},
test_rng, BitIterator, Field, PrimeField,
test_rng, BitIteratorLE, Field, PrimeField,
};
use r1cs_std::{bls12_377::PairingVar as Bls12_377PairingVar, boolean::Boolean, Assignment};
use rand::Rng;
@@ -486,10 +487,7 @@ mod test {
{
for (i, input) in inputs.into_iter().enumerate() {
let mut input_bits = BitIterator::new(input.into_repr()).collect::<Vec<_>>();
// Input must be in little-endian, but BitIterator outputs in big-endian.
input_bits.reverse();
let input_bits: Vec<_> = BitIteratorLE::new(input.into_repr()).collect();
let input_bits =
Vec::<Boolean<Fq>>::new_input(cs.ns(format!("Input {}", i)), || {
Ok(input_bits)
@@ -505,7 +503,7 @@ mod test {
println!("Time to verify!\n\n\n\n");
<TestVerifierGadget as NIZKVerifierGadget<TestProofSystem, Fq>>::verify(
&vk_gadget,
input_gadgets.iter(),
&input_gadgets,
&proof_gadget,
)
.unwrap();
@@ -637,7 +635,7 @@ mod test_recursive {
.map(|chunk| {
chunk
.iter()
.flat_map(|byte| byte.into_bits_le())
.flat_map(|byte| byte.to_bits_le().unwrap())
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
@@ -648,7 +646,7 @@ mod test_recursive {
TestProofVar1::new_witness(cs.ns("Proof"), || Ok(proof.clone())).unwrap();
<TestVerifierGadget1 as NIZKVerifierGadget<TestProofSystem1, MNT6Fq>>::verify(
&vk_gadget,
input_gadgets.iter(),
&input_gadgets,
&proof_gadget,
)?;
Ok(())
@@ -721,12 +719,7 @@ mod test_recursive {
for (i, input) in inputs.into_iter().enumerate() {
let input_gadget =
FpVar::new_input(cs.ns(format!("Input {}", i)), || Ok(input)).unwrap();
let mut fp_bits = input_gadget.to_bits().unwrap();
// FpVar::to_bits outputs a big-endian binary representation of
// fe_gadget's value, so we have to reverse it to get the little-endian
// form.
fp_bits.reverse();
let mut fp_bits = input_gadget.to_bits_le().unwrap();
// Use 320 bits per element.
for _ in fp_bits.len()..bigint_size {
@@ -756,7 +749,7 @@ mod test_recursive {
println!("Time to verify!\n\n\n\n");
<TestVerifierGadget2 as NIZKVerifierGadget<TestProofSystem2, MNT4Fq>>::verify(
&vk_gadget,
input_gadgets.iter(),
&input_gadgets,
&proof_gadget,
)
.unwrap();

View File

@@ -166,7 +166,7 @@ where
fn conditional_verify<'a, T: 'a + ToBitsGadget<E::Fq> + ?Sized>(
vk: &Self::VerificationKeyVar,
input: impl Iterator<Item = &'a T>,
input: impl IntoIterator<Item = &'a T>,
proof: &Self::ProofVar,
condition: &Boolean<E::Fq>,
) -> Result<(), SynthesisError> {
@@ -178,7 +178,7 @@ where
fn conditional_verify_prepared<'a, T: 'a + ToBitsGadget<E::Fq> + ?Sized>(
pvk: &Self::PreparedVerificationKeyVar,
mut public_inputs: impl Iterator<Item = &'a T>,
public_inputs: impl IntoIterator<Item = &'a T>,
proof: &Self::ProofVar,
condition: &Boolean<E::Fq>,
) -> Result<(), SynthesisError> {
@@ -187,8 +187,9 @@ where
let g_ic = {
let mut g_ic: P::G1Var = pvk.gamma_abc_g1[0].clone();
let mut input_len = 1;
let mut public_inputs = public_inputs.into_iter();
for (input, b) in public_inputs.by_ref().zip(pvk.gamma_abc_g1.iter().skip(1)) {
let encoded_input_i: P::G1Var = b.mul_bits(input.to_bits()?.iter())?;
let encoded_input_i: P::G1Var = b.scalar_mul_le(input.to_bits_le()?.iter())?;
g_ic += encoded_input_i;
input_len += 1;
}
@@ -359,7 +360,7 @@ mod test {
use super::*;
use algebra::{
bls12_377::{Bls12_377, Fq, Fr},
test_rng, BitIterator, Field, PrimeField,
test_rng, BitIteratorLE, Field, PrimeField,
};
use r1cs_std::{bls12_377::PairingVar as Bls12_377PairingVar, boolean::Boolean, Assignment};
use rand::Rng;
@@ -447,9 +448,7 @@ mod test {
{
for (i, input) in inputs.into_iter().enumerate() {
let mut input_bits = BitIterator::new(input.into_repr()).collect::<Vec<_>>();
// Input must be in little-endian, but BitIterator outputs in big-endian.
input_bits.reverse();
let input_bits = BitIteratorLE::new(input.into_repr()).collect::<Vec<_>>();
let input_bits =
Vec::<Boolean<Fq>>::new_input(cs.ns(format!("Input {}", i)), || {
@@ -466,7 +465,7 @@ mod test {
println!("Time to verify!\n\n\n\n");
<TestVerifierGadget as NIZKVerifierGadget<TestProofSystem, Fq>>::verify(
&vk_gadget,
input_gadgets.iter(),
&input_gadgets,
&proof_gadget,
)
.unwrap();
@@ -598,7 +597,7 @@ mod test_recursive {
.map(|chunk| {
chunk
.iter()
.flat_map(|byte| byte.into_bits_le())
.flat_map(|byte| byte.to_bits_le().unwrap())
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
@@ -609,7 +608,7 @@ mod test_recursive {
TestProofVar1::new_witness(cs.ns("Proof"), || Ok(proof.clone())).unwrap();
<TestVerifierGadget1 as NIZKVerifierGadget<TestProofSystem1, MNT6Fq>>::verify(
&vk_gadget,
input_gadgets.iter(),
&input_gadgets,
&proof_gadget,
)?;
Ok(())
@@ -682,12 +681,7 @@ mod test_recursive {
for (i, input) in inputs.into_iter().enumerate() {
let input_gadget =
FpVar::new_input(cs.ns(format!("Input {}", i)), || Ok(input)).unwrap();
let mut fp_bits = input_gadget.to_bits().unwrap();
// FpVar::to_bits outputs a big-endian binary representation of
// fe_gadget's value, so we have to reverse it to get the little-endian
// form.
fp_bits.reverse();
let mut fp_bits = input_gadget.to_bits_le().unwrap();
// Use 320 bits per element.
for _ in fp_bits.len()..bigint_size {
@@ -717,7 +711,7 @@ mod test_recursive {
println!("Time to verify!\n\n\n\n");
<TestVerifierGadget2 as NIZKVerifierGadget<TestProofSystem2, MNT4Fq>>::verify(
&vk_gadget,
input_gadgets.iter(),
&input_gadgets,
&proof_gadget,
)
.unwrap();
@@ -728,7 +722,6 @@ mod test_recursive {
println!("=========================================================");
}
// cs.print_named_objects();
assert!(cs.is_satisfied().unwrap());
}
}

View File

@@ -371,7 +371,7 @@ impl<F: PrimeField> PRFGadget<Blake2s, F> for Blake2sGadget {
let input: Vec<_> = seed
.iter()
.chain(input)
.flat_map(|b| b.into_bits_le())
.flat_map(|b| b.to_bits_le().unwrap())
.collect();
let result: Vec<_> = evaluate_blake2s(&input)?
.into_iter()

View File

@@ -54,7 +54,7 @@ pub trait SignatureScheme {
mod test {
use crate::signature::{schnorr, *};
use algebra::{
ed_on_bls12_381::EdwardsProjective as JubJub, groups::Group, test_rng, to_bytes, ToBytes,
ed_on_bls12_381::EdwardsProjective as JubJub, groups::Group, test_rng, to_bytes,
UniformRand,
};
use blake2::Blake2s;

View File

@@ -64,9 +64,9 @@ where
let base = parameters.generator.clone();
let randomness = randomness
.iter()
.flat_map(|b| b.into_bits_le())
.flat_map(|b| b.to_bits_le().unwrap())
.collect::<Vec<_>>();
let rand_pk = &public_key.pub_key + &base.mul_bits(randomness.iter())?;
let rand_pk = &public_key.pub_key + &base.scalar_mul_le(randomness.iter())?;
Ok(PublicKeyVar {
pub_key: rand_pk,
_group: PhantomData,

View File

@@ -163,14 +163,12 @@ where
let randomized_pk = *public_key;
let base = parameters.generator;
let mut encoded = C::zero();
let mut found_one = false;
for bit in bytes_to_bits(randomness).into_iter().rev() {
if found_one {
encoded.double_in_place();
} else {
found_one |= bit;
}
for bit in bytes_to_bits(randomness)
.into_iter()
.rev()
.skip_while(|b| !b)
{
encoded.double_in_place();
if bit {
encoded.add_assign_mixed(&base)
}