Browse Source

Change bit-endianness of into_bits/into_bits_strict.

master
Sean Bowe 7 years ago
parent
commit
543f5cd49c
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
  1. 28
      src/circuit/boolean.rs
  2. 8
      src/circuit/ecc.rs
  3. 28
      src/circuit/mod.rs
  4. 17
      src/circuit/num.rs

28
src/circuit/boolean.rs

@ -301,11 +301,12 @@ pub fn u64_into_boolean_vec_le<E: Engine, CS: ConstraintSystem<E>>(
Ok(bits) Ok(bits)
} }
pub fn field_into_allocated_bits_be<E: Engine, CS: ConstraintSystem<E>, F: PrimeField>( pub fn field_into_allocated_bits_le<E: Engine, CS: ConstraintSystem<E>, F: PrimeField>(
mut cs: CS, mut cs: CS,
value: Option<F> value: Option<F>
) -> Result<Vec<AllocatedBit>, SynthesisError> ) -> Result<Vec<AllocatedBit>, SynthesisError>
{ {
// Deconstruct in big-endian bit order
let values = match value { let values = match value {
Some(ref value) => { Some(ref value) => {
let mut field_char = BitIterator::new(F::char()); let mut field_char = BitIterator::new(F::char());
@ -332,7 +333,8 @@ pub fn field_into_allocated_bits_be<E: Engine, CS: ConstraintSystem<E>, F: Prime
} }
}; };
let bits = values.into_iter().enumerate().map(|(i, b)| { // Allocate in little-endian order
let bits = values.into_iter().rev().enumerate().map(|(i, b)| {
AllocatedBit::alloc( AllocatedBit::alloc(
cs.namespace(|| format!("bit {}", i)), cs.namespace(|| format!("bit {}", i)),
b b
@ -512,7 +514,7 @@ mod test {
use super::{ use super::{
AllocatedBit, AllocatedBit,
Boolean, Boolean,
field_into_allocated_bits_be, field_into_allocated_bits_le,
u64_into_boolean_vec_le u64_into_boolean_vec_le
}; };
@ -1003,24 +1005,24 @@ mod test {
} }
#[test] #[test]
fn test_field_into_allocated_bits_be() { fn test_field_into_allocated_bits_le() {
let mut cs = TestConstraintSystem::<Bls12>::new(); let mut cs = TestConstraintSystem::<Bls12>::new();
let r = Fr::from_str("9147677615426976802526883532204139322118074541891858454835346926874644257775").unwrap(); let r = Fr::from_str("9147677615426976802526883532204139322118074541891858454835346926874644257775").unwrap();
let bits = field_into_allocated_bits_be(&mut cs, Some(r)).unwrap(); let bits = field_into_allocated_bits_le(&mut cs, Some(r)).unwrap();
assert!(cs.is_satisfied()); assert!(cs.is_satisfied());
assert_eq!(bits.len(), 255); assert_eq!(bits.len(), 255);
assert_eq!(bits[0].value.unwrap(), false); assert_eq!(bits[254 - 0].value.unwrap(), false);
assert_eq!(bits[1].value.unwrap(), false); assert_eq!(bits[254 - 1].value.unwrap(), false);
assert_eq!(bits[2].value.unwrap(), true); assert_eq!(bits[254 - 2].value.unwrap(), true);
assert_eq!(bits[3].value.unwrap(), false); assert_eq!(bits[254 - 3].value.unwrap(), false);
assert_eq!(bits[4].value.unwrap(), true); assert_eq!(bits[254 - 4].value.unwrap(), true);
assert_eq!(bits[5].value.unwrap(), false); assert_eq!(bits[254 - 5].value.unwrap(), false);
assert_eq!(bits[20].value.unwrap(), true); assert_eq!(bits[254 - 20].value.unwrap(), true);
assert_eq!(bits[23].value.unwrap(), true); assert_eq!(bits[254 - 23].value.unwrap(), true);
} }
} }

8
src/circuit/ecc.rs

@ -105,18 +105,14 @@ impl<E: JubjubEngine> EdwardsPoint<E> {
{ {
let mut tmp = vec![]; let mut tmp = vec![];
let mut x = self.x.into_bits_strict( let x = self.x.into_bits_strict(
cs.namespace(|| "unpack x") cs.namespace(|| "unpack x")
)?; )?;
let mut y = self.y.into_bits_strict( let y = self.y.into_bits_strict(
cs.namespace(|| "unpack y") cs.namespace(|| "unpack y")
)?; )?;
// We want the representation in little endian bit order
x.reverse();
y.reverse();
tmp.extend(y); tmp.extend(y);
tmp.push(x[0].clone()); tmp.push(x[0].clone());

28
src/circuit/mod.rs

@ -81,12 +81,11 @@ impl<'a, E: JubjubEngine> Circuit<E> for Spend<'a, E> {
)?; )?;
// Booleanize the randomness // Booleanize the randomness
let hr = boolean::field_into_allocated_bits_be( let hr = boolean::field_into_allocated_bits_le(
cs.namespace(|| "hr"), cs.namespace(|| "hr"),
self.value_randomness self.value_randomness
)? )?
.into_iter() .into_iter()
.rev() // Little endian bit order
.map(|e| boolean::Boolean::from(e)) .map(|e| boolean::Boolean::from(e))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -110,13 +109,13 @@ impl<'a, E: JubjubEngine> Circuit<E> for Spend<'a, E> {
let rk; let rk;
{ {
// Witness rsk as bits // Witness rsk as bits
let rsk = boolean::field_into_allocated_bits_be( let rsk = boolean::field_into_allocated_bits_le(
cs.namespace(|| "rsk"), cs.namespace(|| "rsk"),
self.rsk self.rsk
)? )?
.into_iter() .into_iter()
.rev() // We need it in little endian bit order .map(|e| boolean::Boolean::from(e))
.map(|e| boolean::Boolean::from(e)).collect::<Vec<_>>(); .collect::<Vec<_>>();
// NB: We don't ensure that the bit representation of rsk // NB: We don't ensure that the bit representation of rsk
// is "in the field" (Fs) because it's not used except to // is "in the field" (Fs) because it's not used except to
@ -206,12 +205,11 @@ impl<'a, E: JubjubEngine> Circuit<E> for Spend<'a, E> {
{ {
// Booleanize the randomness // Booleanize the randomness
let cmr = boolean::field_into_allocated_bits_be( let cmr = boolean::field_into_allocated_bits_le(
cs.namespace(|| "cmr"), cs.namespace(|| "cmr"),
self.commitment_randomness self.commitment_randomness
)? )?
.into_iter() .into_iter()
.rev() // We need it in little endian bit order
.map(|e| boolean::Boolean::from(e)) .map(|e| boolean::Boolean::from(e))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -358,12 +356,11 @@ impl<'a, E: JubjubEngine> Circuit<E> for Output<'a, E> {
)?; )?;
// Booleanize the randomness // Booleanize the randomness
let hr = boolean::field_into_allocated_bits_be( let hr = boolean::field_into_allocated_bits_le(
cs.namespace(|| "hr"), cs.namespace(|| "hr"),
self.value_randomness self.value_randomness
)? )?
.into_iter() .into_iter()
.rev() // Little endian bit order
.map(|e| boolean::Boolean::from(e)) .map(|e| boolean::Boolean::from(e))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -422,12 +419,11 @@ impl<'a, E: JubjubEngine> Circuit<E> for Output<'a, E> {
); );
// Compute epk from esk // Compute epk from esk
let esk = boolean::field_into_allocated_bits_be( let esk = boolean::field_into_allocated_bits_le(
cs.namespace(|| "esk"), cs.namespace(|| "esk"),
self.esk self.esk
)? )?
.into_iter() .into_iter()
.rev() // We need it in little endian bit order
.map(|e| boolean::Boolean::from(e)) .map(|e| boolean::Boolean::from(e))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -446,12 +442,11 @@ impl<'a, E: JubjubEngine> Circuit<E> for Output<'a, E> {
{ {
let p_d = self.p_d.map(|e| e.into_xy()); let p_d = self.p_d.map(|e| e.into_xy());
let y_contents = boolean::field_into_allocated_bits_be( let y_contents = boolean::field_into_allocated_bits_le(
cs.namespace(|| "p_d bits of y"), cs.namespace(|| "p_d bits of y"),
p_d.map(|e| e.1) p_d.map(|e| e.1)
)? )?
.into_iter() .into_iter()
.rev() // We need it in little endian bit order
.map(|e| boolean::Boolean::from(e)) .map(|e| boolean::Boolean::from(e))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -481,12 +476,11 @@ impl<'a, E: JubjubEngine> Circuit<E> for Output<'a, E> {
{ {
// Booleanize the randomness // Booleanize the randomness
let cmr = boolean::field_into_allocated_bits_be( let cmr = boolean::field_into_allocated_bits_le(
cs.namespace(|| "cmr"), cs.namespace(|| "cmr"),
self.commitment_randomness self.commitment_randomness
)? )?
.into_iter() .into_iter()
.rev() // We need it in little endian bit order
.map(|e| boolean::Boolean::from(e)) .map(|e| boolean::Boolean::from(e))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -552,7 +546,7 @@ fn test_input_circuit_with_bls12_381() {
assert!(cs.is_satisfied()); assert!(cs.is_satisfied());
assert_eq!(cs.num_constraints(), 97379); assert_eq!(cs.num_constraints(), 97379);
assert_eq!(cs.hash(), "a3ac418bbbe38d08295995c8cdcaebd6902fcfa9e4f7212c9742ed033c1edec3"); assert_eq!(cs.hash(), "db283e10d01d6c3c4d23cd3c05a7ae8f1a7d8091a39f8d8b604e610ca6a3e496");
} }
} }
@ -590,6 +584,6 @@ fn test_output_circuit_with_bls12_381() {
assert!(cs.is_satisfied()); assert!(cs.is_satisfied());
assert_eq!(cs.num_constraints(), 7827); assert_eq!(cs.num_constraints(), 7827);
assert_eq!(cs.hash(), "b74e3ee749e1cbc405b5b4a1de3b11119084afda9b6f5e3a6865cbcc5c35e3d4"); assert_eq!(cs.hash(), "ccb2ad9a6d492e708da155305064a3b8af5d29b4b766cf08ac415a478aae4cc6");
} }
} }

17
src/circuit/num.rs

@ -83,6 +83,11 @@ impl<E: Engine> AllocatedNum<E> {
Ok(()) Ok(())
} }
/// Deconstructs this allocated number into its
/// boolean representation in little-endian bit
/// order, requiring that the representation
/// strictly exists "in the field" (i.e., a
/// congruency is not allowed.)
pub fn into_bits_strict<CS>( pub fn into_bits_strict<CS>(
&self, &self,
mut cs: CS mut cs: CS
@ -208,16 +213,20 @@ impl<E: Engine> AllocatedNum<E> {
|_| lc |_| lc
); );
Ok(result.into_iter().map(|b| Boolean::from(b)).collect()) // Convert into booleans, and reverse for little-endian bit order
Ok(result.into_iter().map(|b| Boolean::from(b)).rev().collect())
} }
/// Convert the allocated number into its little-endian representation.
/// Note that this does not strongly enforce that the commitment is
/// "in the field."
pub fn into_bits<CS>( pub fn into_bits<CS>(
&self, &self,
mut cs: CS mut cs: CS
) -> Result<Vec<Boolean>, SynthesisError> ) -> Result<Vec<Boolean>, SynthesisError>
where CS: ConstraintSystem<E> where CS: ConstraintSystem<E>
{ {
let bits = boolean::field_into_allocated_bits_be( let bits = boolean::field_into_allocated_bits_le(
&mut cs, &mut cs,
self.value self.value
)?; )?;
@ -225,7 +234,7 @@ impl<E: Engine> AllocatedNum<E> {
let mut lc = LinearCombination::zero(); let mut lc = LinearCombination::zero();
let mut coeff = E::Fr::one(); let mut coeff = E::Fr::one();
for bit in bits.iter().rev() { for bit in bits.iter() {
lc = lc + (coeff, bit.get_variable()); lc = lc + (coeff, bit.get_variable());
coeff.double(); coeff.double();
@ -585,7 +594,7 @@ mod test {
assert!(cs.is_satisfied()); assert!(cs.is_satisfied());
for (b, a) in BitIterator::new(r.into_repr()).skip(1).zip(bits.iter()) { for (b, a) in BitIterator::new(r.into_repr()).skip(1).zip(bits.iter().rev()) {
if let &Boolean::Is(ref a) = a { if let &Boolean::Is(ref a) = a {
assert_eq!(b, a.get_value().unwrap()); assert_eq!(b, a.get_value().unwrap());
} else { } else {

Loading…
Cancel
Save