Browse Source

Rename AllocatedBit to AllocatedBool (#60)

* Rename AllocatedBit to AllocatedBool

* Update Changelog

* Fix independent fmt issues
master
Dev Ojha 3 years ago
committed by GitHub
parent
commit
5debc6f8f1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 49 deletions
  1. +14
    -0
      CHANGELOG.md
  2. +30
    -30
      src/bits/boolean.rs
  3. +23
    -19
      src/bits/uint.rs

+ 14
- 0
CHANGELOG.md

@ -1,3 +1,17 @@
## Pending
### Breaking changes
- #60 Rename `AllocatedBit` to `AllocatedBool` for consistency with the `Boolean` variable.
You can update downstream usage with `grep -rl 'AllocatedBit' . | xargs env LANG=C env LC_CTYPE=C sed -i '' 's/AllocatedBit/AllocatedBool/g'`.
### Features
### Improvements
### Bug Fixes
## v0.2.0 ## v0.2.0
### Breaking changes ### Breaking changes

+ 30
- 30
src/bits/boolean.rs

@ -9,12 +9,12 @@ use core::borrow::Borrow;
/// Represents a variable in the constraint system which is guaranteed /// Represents a variable in the constraint system which is guaranteed
/// to be either zero or one. /// to be either zero or one.
/// ///
/// In general, one should prefer using `Boolean` instead of `AllocatedBit`,
/// In general, one should prefer using `Boolean` instead of `AllocatedBool`,
/// as `Boolean` offers better support for constant values, and implements /// as `Boolean` offers better support for constant values, and implements
/// more traits. /// more traits.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
#[must_use] #[must_use]
pub struct AllocatedBit<F: Field> {
pub struct AllocatedBool<F: Field> {
variable: Variable, variable: Variable,
cs: ConstraintSystemRef<F>, cs: ConstraintSystemRef<F>,
} }
@ -27,7 +27,7 @@ pub(crate) fn bool_to_field(val: impl Borrow) -> F {
} }
} }
impl<F: Field> AllocatedBit<F> {
impl<F: Field> AllocatedBool<F> {
/// Get the assigned value for `self`. /// Get the assigned value for `self`.
pub fn value(&self) -> Result<bool, SynthesisError> { pub fn value(&self) -> Result<bool, SynthesisError> {
let value = self.cs.assigned_value(self.variable).get()?; let value = self.cs.assigned_value(self.variable).get()?;
@ -55,7 +55,7 @@ impl AllocatedBit {
} }
/// Performs an XOR operation over the two operands, returning /// Performs an XOR operation over the two operands, returning
/// an `AllocatedBit`.
/// an `AllocatedBool`.
#[tracing::instrument(target = "r1cs")] #[tracing::instrument(target = "r1cs")]
pub fn xor(&self, b: &Self) -> Result<Self, SynthesisError> { pub fn xor(&self, b: &Self) -> Result<Self, SynthesisError> {
let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || { let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || {
@ -87,7 +87,7 @@ impl AllocatedBit {
} }
/// Performs an AND operation over the two operands, returning /// Performs an AND operation over the two operands, returning
/// an `AllocatedBit`.
/// an `AllocatedBool`.
#[tracing::instrument(target = "r1cs")] #[tracing::instrument(target = "r1cs")]
pub fn and(&self, b: &Self) -> Result<Self, SynthesisError> { pub fn and(&self, b: &Self) -> Result<Self, SynthesisError> {
let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || { let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || {
@ -106,7 +106,7 @@ impl AllocatedBit {
} }
/// Performs an OR operation over the two operands, returning /// Performs an OR operation over the two operands, returning
/// an `AllocatedBit`.
/// an `AllocatedBool`.
#[tracing::instrument(target = "r1cs")] #[tracing::instrument(target = "r1cs")]
pub fn or(&self, b: &Self) -> Result<Self, SynthesisError> { pub fn or(&self, b: &Self) -> Result<Self, SynthesisError> {
let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || { let result = Self::new_witness_without_booleanity_check(self.cs.clone(), || {
@ -161,7 +161,7 @@ impl AllocatedBit {
} }
} }
impl<F: Field> AllocVar<bool, F> for AllocatedBit<F> {
impl<F: Field> AllocVar<bool, F> for AllocatedBool<F> {
/// Produces a new variable of the appropriate kind /// Produces a new variable of the appropriate kind
/// (instance or witness), with a booleanity check. /// (instance or witness), with a booleanity check.
/// ///
@ -199,7 +199,7 @@ impl AllocVar for AllocatedBit {
} }
} }
impl<F: Field> CondSelectGadget<F> for AllocatedBit<F> {
impl<F: Field> CondSelectGadget<F> for AllocatedBool<F> {
#[tracing::instrument(target = "r1cs")] #[tracing::instrument(target = "r1cs")]
fn conditionally_select( fn conditionally_select(
cond: &Boolean<F>, cond: &Boolean<F>,
@ -224,9 +224,9 @@ impl CondSelectGadget for AllocatedBit {
#[must_use] #[must_use]
pub enum Boolean<F: Field> { pub enum Boolean<F: Field> {
/// Existential view of the boolean variable. /// Existential view of the boolean variable.
Is(AllocatedBit<F>),
Is(AllocatedBool<F>),
/// Negated view of the boolean variable. /// Negated view of the boolean variable.
Not(AllocatedBit<F>),
Not(AllocatedBool<F>),
/// Constant (not an allocated variable). /// Constant (not an allocated variable).
Constant(bool), Constant(bool),
} }
@ -772,8 +772,8 @@ impl Boolean {
} }
} }
impl<F: Field> From<AllocatedBit<F>> for Boolean<F> {
fn from(b: AllocatedBit<F>) -> Self {
impl<F: Field> From<AllocatedBool<F>> for Boolean<F> {
fn from(b: AllocatedBool<F>) -> Self {
Boolean::Is(b) Boolean::Is(b)
} }
} }
@ -787,7 +787,7 @@ impl AllocVar for Boolean {
if mode == AllocationMode::Constant { if mode == AllocationMode::Constant {
Ok(Boolean::Constant(*f()?.borrow())) Ok(Boolean::Constant(*f()?.borrow()))
} else { } else {
AllocatedBit::new_variable(cs, f, mode).map(Boolean::from)
AllocatedBool::new_variable(cs, f, mode).map(Boolean::from)
} }
} }
} }
@ -916,7 +916,7 @@ impl CondSelectGadget for Boolean {
(a, b) => { (a, b) => {
let cs = cond.cs(); let cs = cond.cs();
let result: Boolean<F> = let result: Boolean<F> =
AllocatedBit::new_witness_without_booleanity_check(cs.clone(), || {
AllocatedBool::new_witness_without_booleanity_check(cs.clone(), || {
let cond = cond.value()?; let cond = cond.value()?;
Ok(if cond { a.value()? } else { b.value()? }) Ok(if cond { a.value()? } else { b.value()? })
})? })?
@ -954,7 +954,7 @@ impl CondSelectGadget for Boolean {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{AllocatedBit, Boolean};
use super::{AllocatedBool, Boolean};
use crate::prelude::*; use crate::prelude::*;
use ark_ff::{BitIteratorBE, BitIteratorLE, Field, One, PrimeField, UniformRand, Zero}; use ark_ff::{BitIteratorBE, BitIteratorLE, Field, One, PrimeField, UniformRand, Zero};
use ark_relations::r1cs::{ConstraintSystem, Namespace, SynthesisError}; use ark_relations::r1cs::{ConstraintSystem, Namespace, SynthesisError};
@ -982,9 +982,9 @@ mod test {
for a_val in [false, true].iter().copied() { for a_val in [false, true].iter().copied() {
for b_val in [false, true].iter().copied() { for b_val in [false, true].iter().copied() {
let cs = ConstraintSystem::<Fr>::new_ref(); let cs = ConstraintSystem::<Fr>::new_ref();
let a = AllocatedBit::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBit::xor(&a, &b)?;
let a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBool::xor(&a, &b)?;
assert_eq!(c.value()?, a_val ^ b_val); assert_eq!(c.value()?, a_val ^ b_val);
assert!(cs.is_satisfied().unwrap()); assert!(cs.is_satisfied().unwrap());
@ -1001,9 +1001,9 @@ mod test {
for a_val in [false, true].iter().copied() { for a_val in [false, true].iter().copied() {
for b_val in [false, true].iter().copied() { for b_val in [false, true].iter().copied() {
let cs = ConstraintSystem::<Fr>::new_ref(); let cs = ConstraintSystem::<Fr>::new_ref();
let a = AllocatedBit::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBit::or(&a, &b)?;
let a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBool::or(&a, &b)?;
assert_eq!(c.value()?, a_val | b_val); assert_eq!(c.value()?, a_val | b_val);
assert!(cs.is_satisfied().unwrap()); assert!(cs.is_satisfied().unwrap());
@ -1020,9 +1020,9 @@ mod test {
for a_val in [false, true].iter().copied() { for a_val in [false, true].iter().copied() {
for b_val in [false, true].iter().copied() { for b_val in [false, true].iter().copied() {
let cs = ConstraintSystem::<Fr>::new_ref(); let cs = ConstraintSystem::<Fr>::new_ref();
let a = AllocatedBit::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBit::and(&a, &b)?;
let a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBool::and(&a, &b)?;
assert_eq!(c.value()?, a_val & b_val); assert_eq!(c.value()?, a_val & b_val);
assert!(cs.is_satisfied().unwrap()); assert!(cs.is_satisfied().unwrap());
@ -1039,9 +1039,9 @@ mod test {
for a_val in [false, true].iter().copied() { for a_val in [false, true].iter().copied() {
for b_val in [false, true].iter().copied() { for b_val in [false, true].iter().copied() {
let cs = ConstraintSystem::<Fr>::new_ref(); let cs = ConstraintSystem::<Fr>::new_ref();
let a = AllocatedBit::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBit::and_not(&a, &b)?;
let a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBool::and_not(&a, &b)?;
assert_eq!(c.value()?, a_val & !b_val); assert_eq!(c.value()?, a_val & !b_val);
assert!(cs.is_satisfied().unwrap()); assert!(cs.is_satisfied().unwrap());
@ -1058,9 +1058,9 @@ mod test {
for a_val in [false, true].iter().copied() { for a_val in [false, true].iter().copied() {
for b_val in [false, true].iter().copied() { for b_val in [false, true].iter().copied() {
let cs = ConstraintSystem::<Fr>::new_ref(); let cs = ConstraintSystem::<Fr>::new_ref();
let a = AllocatedBit::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBit::nor(&a, &b)?;
let a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
let c = AllocatedBool::nor(&a, &b)?;
assert_eq!(c.value()?, !a_val & !b_val); assert_eq!(c.value()?, !a_val & !b_val);
assert!(cs.is_satisfied().unwrap()); assert!(cs.is_satisfied().unwrap());

+ 23
- 19
src/bits/uint.rs

@ -17,7 +17,7 @@ macro_rules! make_uint {
}; };
use crate::{ use crate::{
boolean::{AllocatedBit, Boolean},
boolean::{AllocatedBool, Boolean},
prelude::*, prelude::*,
Assignment, Vec, Assignment, Vec,
}; };
@ -128,18 +128,15 @@ macro_rules! make_uint {
let mut result = self.clone(); let mut result = self.clone();
let by = by % $size; let by = by % $size;
let new_bits = self
.bits
.iter()
.skip(by)
.chain(&self.bits)
.take($size);
let new_bits = self.bits.iter().skip(by).chain(&self.bits).take($size);
for (res, new) in result.bits.iter_mut().zip(new_bits) { for (res, new) in result.bits.iter_mut().zip(new_bits) {
*res = new.clone(); *res = new.clone();
} }
result.value = self.value.map(|v| v.rotate_right(u32::try_from(by).unwrap()));
result.value = self
.value
.map(|v| v.rotate_right(u32::try_from(by).unwrap()));
result result
} }
@ -188,7 +185,8 @@ macro_rules! make_uint {
// Compute the maximum value of the sum so we allocate enough bits for // Compute the maximum value of the sum so we allocate enough bits for
// the result // the result
let mut max_value = BigUint::from($native::max_value()) * BigUint::from(operands.len());
let mut max_value =
BigUint::from($native::max_value()) * BigUint::from(operands.len());
// Keep track of the resulting value // Keep track of the resulting value
let mut result_value = Some(BigUint::zero()); let mut result_value = Some(BigUint::zero());
@ -242,12 +240,10 @@ macro_rules! make_uint {
} }
// The value of the actual result is modulo 2^$size // The value of the actual result is modulo 2^$size
let modular_value = result_value.clone().map(|v|
{
let modulus = BigUint::from(1u64) << ($size as u32);
(v % modulus).to_u128().unwrap() as $native
}
);
let modular_value = result_value.clone().map(|v| {
let modulus = BigUint::from(1u64) << ($size as u32);
(v % modulus).to_u128().unwrap() as $native
});
if all_constants && modular_value.is_some() { if all_constants && modular_value.is_some() {
// We can just return a constant, rather than // We can just return a constant, rather than
@ -265,7 +261,12 @@ macro_rules! make_uint {
let mut i = 0; let mut i = 0;
while max_value != BigUint::zero() { while max_value != BigUint::zero() {
// Allocate the bit_gadget // Allocate the bit_gadget
let b = AllocatedBit::new_witness(cs.clone(), || result_value.clone().map(|v| (v >> i) & BigUint::one() == BigUint::one()).get())?;
let b = AllocatedBool::new_witness(cs.clone(), || {
result_value
.clone()
.map(|v| (v >> i) & BigUint::one() == BigUint::one())
.get()
})?;
// Subtract this bit_gadget from the linear combination to ensure the sums // Subtract this bit_gadget from the linear combination to ensure the sums
// balance out // balance out
@ -369,11 +370,14 @@ macro_rules! make_uint {
let mut values = [None; $size]; let mut values = [None; $size];
if let Some(val) = value { if let Some(val) = value {
values.iter_mut().enumerate().for_each(|(i, v)| *v = Some((val >> i) & 1 == 1));
values
.iter_mut()
.enumerate()
.for_each(|(i, v)| *v = Some((val >> i) & 1 == 1));
} }
let mut bits = [Boolean::FALSE; $size]; let mut bits = [Boolean::FALSE; $size];
for (b, v) in bits.iter_mut().zip(&values) {
for (b, v) in bits.iter_mut().zip(&values) {
*b = Boolean::new_variable(cs.clone(), || v.get(), mode)?; *b = Boolean::new_variable(cs.clone(), || v.get(), mode)?;
} }
Ok(Self { bits, value }) Ok(Self { bits, value })
@ -384,9 +388,9 @@ macro_rules! make_uint {
mod test { mod test {
use super::$name; use super::$name;
use crate::{bits::boolean::Boolean, prelude::*, Vec}; use crate::{bits::boolean::Boolean, prelude::*, Vec};
use ark_test_curves::mnt4_753::Fr;
use ark_relations::r1cs::{ConstraintSystem, SynthesisError}; use ark_relations::r1cs::{ConstraintSystem, SynthesisError};
use ark_std::rand::Rng; use ark_std::rand::Rng;
use ark_test_curves::mnt4_753::Fr;
#[test] #[test]
fn test_from_bits() -> Result<(), SynthesisError> { fn test_from_bits() -> Result<(), SynthesisError> {

Loading…
Cancel
Save