diff --git a/src/circuit/boolean.rs b/src/circuit/boolean.rs index 4d1c358..c6cb088 100644 --- a/src/circuit/boolean.rs +++ b/src/circuit/boolean.rs @@ -234,6 +234,47 @@ impl AllocatedBit { } } +pub fn field_into_allocated_bits_be, F: PrimeField>( + mut cs: CS, + value: Option +) -> Result, SynthesisError> +{ + let values = match value { + Some(ref value) => { + let mut field_char = BitIterator::new(F::char()); + + let mut tmp = Vec::with_capacity(F::NUM_BITS as usize); + + let mut found_one = false; + for b in BitIterator::new(value.into_repr()) { + // Skip leading bits + found_one |= field_char.next().unwrap(); + if !found_one { + continue; + } + + tmp.push(Some(b)); + } + + assert_eq!(tmp.len(), F::NUM_BITS as usize); + + tmp + }, + None => { + vec![None; F::NUM_BITS as usize] + } + }; + + let bits = values.into_iter().enumerate().map(|(i, b)| { + AllocatedBit::alloc( + cs.namespace(|| format!("bit {}", i)), + b + ) + }).collect::, SynthesisError>>()?; + + Ok(bits) +} + /// This is a boolean value which may be either a constant or /// an interpretation of an `AllocatedBit`. #[derive(Clone)] @@ -509,7 +550,11 @@ mod test { use pairing::bls12_381::{Bls12, Fr}; use pairing::{Field, PrimeField, PrimeFieldRepr, BitIterator}; use ::circuit::test::*; - use super::{AllocatedBit, Boolean}; + use super::{ + AllocatedBit, + Boolean, + field_into_allocated_bits_be + }; #[test] fn test_allocated_bit() { @@ -1129,4 +1174,26 @@ mod test { } } } + + #[test] + fn test_field_into_allocated_bits_be() { + let mut cs = TestConstraintSystem::::new(); + + let r = Fr::from_str("9147677615426976802526883532204139322118074541891858454835346926874644257775").unwrap(); + + let bits = field_into_allocated_bits_be(&mut cs, Some(r)).unwrap(); + + assert!(cs.is_satisfied()); + + assert_eq!(bits.len(), 255); + + assert_eq!(bits[0].value.unwrap(), false); + assert_eq!(bits[1].value.unwrap(), false); + assert_eq!(bits[2].value.unwrap(), true); + assert_eq!(bits[3].value.unwrap(), false); + assert_eq!(bits[4].value.unwrap(), true); + assert_eq!(bits[5].value.unwrap(), false); + assert_eq!(bits[20].value.unwrap(), true); + assert_eq!(bits[23].value.unwrap(), true); + } } diff --git a/src/circuit/num.rs b/src/circuit/num.rs index aca7562..a6505f6 100644 --- a/src/circuit/num.rs +++ b/src/circuit/num.rs @@ -17,8 +17,9 @@ use super::{ }; use super::boolean::{ - Boolean, - AllocatedBit + self, + Boolean, + AllocatedBit }; pub struct AllocatedNum { @@ -76,39 +77,10 @@ impl AllocatedNum { ) -> Result, SynthesisError> where CS: ConstraintSystem { - let bit_values = match self.value { - Some(value) => { - let mut field_char = BitIterator::new(E::Fr::char()); - - let mut tmp = Vec::with_capacity(E::Fr::NUM_BITS as usize); - - let mut found_one = false; - for b in BitIterator::new(value.into_repr()) { - // Skip leading bits - found_one |= field_char.next().unwrap(); - if !found_one { - continue; - } - - tmp.push(Some(b)); - } - - assert_eq!(tmp.len(), E::Fr::NUM_BITS as usize); - - tmp - }, - None => { - vec![None; E::Fr::NUM_BITS as usize] - } - }; - - let mut bits = vec![]; - for (i, b) in bit_values.into_iter().enumerate() { - bits.push(AllocatedBit::alloc( - cs.namespace(|| format!("bit {}", i)), - b - )?); - } + let bits = boolean::field_into_allocated_bits_be( + &mut cs, + self.value + )?; let mut lc = LinearCombination::zero(); let mut coeff = E::Fr::one();