Change bit-endianness of into_bits/into_bits_strict.

This commit is contained in:
Sean Bowe 2018-03-05 10:27:14 -07:00
parent 3e15751fd1
commit 543f5cd49c
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
4 changed files with 41 additions and 40 deletions

View File

@ -301,11 +301,12 @@ pub fn u64_into_boolean_vec_le<E: Engine, CS: ConstraintSystem<E>>(
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,
value: Option<F>
) -> Result<Vec<AllocatedBit>, SynthesisError>
{
// Deconstruct in big-endian bit order
let values = match value {
Some(ref value) => {
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(
cs.namespace(|| format!("bit {}", i)),
b
@ -512,7 +514,7 @@ mod test {
use super::{
AllocatedBit,
Boolean,
field_into_allocated_bits_be,
field_into_allocated_bits_le,
u64_into_boolean_vec_le
};
@ -1003,24 +1005,24 @@ mod test {
}
#[test]
fn test_field_into_allocated_bits_be() {
fn test_field_into_allocated_bits_le() {
let mut cs = TestConstraintSystem::<Bls12>::new();
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_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);
assert_eq!(bits[254 - 0].value.unwrap(), false);
assert_eq!(bits[254 - 1].value.unwrap(), false);
assert_eq!(bits[254 - 2].value.unwrap(), true);
assert_eq!(bits[254 - 3].value.unwrap(), false);
assert_eq!(bits[254 - 4].value.unwrap(), true);
assert_eq!(bits[254 - 5].value.unwrap(), false);
assert_eq!(bits[254 - 20].value.unwrap(), true);
assert_eq!(bits[254 - 23].value.unwrap(), true);
}
}

View File

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

View File

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

View File

@ -83,6 +83,11 @@ impl<E: Engine> AllocatedNum<E> {
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>(
&self,
mut cs: CS
@ -208,16 +213,20 @@ impl<E: Engine> AllocatedNum<E> {
|_| 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>(
&self,
mut cs: CS
) -> Result<Vec<Boolean>, SynthesisError>
where CS: ConstraintSystem<E>
{
let bits = boolean::field_into_allocated_bits_be(
let bits = boolean::field_into_allocated_bits_le(
&mut cs,
self.value
)?;
@ -225,7 +234,7 @@ impl<E: Engine> AllocatedNum<E> {
let mut lc = LinearCombination::zero();
let mut coeff = E::Fr::one();
for bit in bits.iter().rev() {
for bit in bits.iter() {
lc = lc + (coeff, bit.get_variable());
coeff.double();
@ -585,7 +594,7 @@ mod test {
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 {
assert_eq!(b, a.get_value().unwrap());
} else {