Change bit-endianness of into_bits/into_bits_strict.
This commit is contained in:
parent
3e15751fd1
commit
543f5cd49c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue