mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-09 07:21:29 +01:00
Rename AllocatedBit to AllocatedBool (#60)
* Rename AllocatedBit to AllocatedBool * Update Changelog * Fix independent fmt issues
This commit is contained in:
14
CHANGELOG.md
14
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
|
||||||
|
|||||||
@@ -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<F: Field>(val: impl Borrow<bool>) -> 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<F: Field> AllocatedBit<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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<F: Field> AllocatedBit<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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<F: Field> AllocatedBit<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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<F: Field> AllocatedBit<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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<F: Field> AllocVar<bool, F> for AllocatedBit<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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<F: Field> CondSelectGadget<F> for AllocatedBit<F> {
|
|||||||
#[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<F: Field> Boolean<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field> From<AllocatedBit<F>> for Boolean<F> {
|
impl<F: Field> From<AllocatedBool<F>> for Boolean<F> {
|
||||||
fn from(b: AllocatedBit<F>) -> Self {
|
fn from(b: AllocatedBool<F>) -> Self {
|
||||||
Boolean::Is(b)
|
Boolean::Is(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -787,7 +787,7 @@ impl<F: Field> AllocVar<bool, F> for Boolean<F> {
|
|||||||
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<F: Field> CondSelectGadget<F> for Boolean<F> {
|
|||||||
(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<F: Field> CondSelectGadget<F> for Boolean<F> {
|
|||||||
|
|
||||||
#[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 a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
|
||||||
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
|
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
|
||||||
let c = AllocatedBit::xor(&a, &b)?;
|
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 a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
|
||||||
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
|
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
|
||||||
let c = AllocatedBit::or(&a, &b)?;
|
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 a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
|
||||||
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
|
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
|
||||||
let c = AllocatedBit::and(&a, &b)?;
|
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 a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
|
||||||
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
|
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
|
||||||
let c = AllocatedBit::and_not(&a, &b)?;
|
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 a = AllocatedBool::new_witness(cs.clone(), || Ok(a_val))?;
|
||||||
let b = AllocatedBit::new_witness(cs.clone(), || Ok(b_val))?;
|
let b = AllocatedBool::new_witness(cs.clone(), || Ok(b_val))?;
|
||||||
let c = AllocatedBit::nor(&a, &b)?;
|
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());
|
||||||
|
|||||||
@@ -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
|
let new_bits = self.bits.iter().skip(by).chain(&self.bits).take($size);
|
||||||
.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 modular_value = result_value.clone().map(|v| {
|
||||||
{
|
let modulus = BigUint::from(1u64) << ($size as u32);
|
||||||
let modulus = BigUint::from(1u64) << ($size as u32);
|
(v % modulus).to_u128().unwrap() as $native
|
||||||
(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> {
|
||||||
|
|||||||
Reference in New Issue
Block a user