Skip to content

Commit

Permalink
Add back ToBytesGadget and ToBitsGadget to prelude (#136)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pratyush authored Jan 6, 2024
1 parent d011859 commit a124995
Show file tree
Hide file tree
Showing 26 changed files with 874 additions and 231 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@

### Breaking changes

- [\#121](https://github.com/arkworks-rs/r1cs-std/pull/121)
- Refactor `UInt{8,16,64,128}` into one struct `UInt`.
- Remove `bits` module.
- Use `std::ops` traits for `UInt` and `Boolean`.
- [\#134](https://github.com/arkworks-rs/r1cs-std/pull/134) Add `Mul<NonnativeFieldVar>` bounds and impls for `CurveVar`.
- [\#135](https://github.com/arkworks-rs/r1cs-std/pull/135)
- Rename `NonNativeFieldVar` to `EmulatedFpVar`.
- Rename `fields::nonnative` to `fields::emulated_fp`.
- Rename `fields::nonnative::{Allocated}NonNativeMulResultVar` to `fields::emulated_fp::{Allocated}MulResultVar`.
- [\#136](https://github.com/arkworks-rs/r1cs-std/pull/136)
- Rename `ToBytesGadget::to_{non_unique_}bytes``ToBytesGadget::to_{non_unique_}bytes_in_le`.

### Features

- [\#136](https://github.com/arkworks-rs/r1cs-std/pull/136)
- Add `{BitAnd,BitOr,BitXor,BitAndAssign,BitOrAssign,BitXorAssign}<T> for UInt<N, T, F>`.
- Add `UInt::rotate_{left,right}_in_place`.
- Add `{Boolean,UInt}::not_in_place`.
- Add `UInt::{from_bytes_le, from_bytes_be, to_bytes_be}`.

### Improvements

### Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion src/boolean/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::convert::{ToBytesGadget, ToConstraintFieldGadget};
impl<F: Field> ToBytesGadget<F> for Boolean<F> {
/// Outputs `1u8` if `self` is true, and `0u8` otherwise.
#[tracing::instrument(target = "r1cs")]
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
let value = self.value().map(u8::from).ok();
let mut bits = [Boolean::FALSE; 8];
bits[0] = self.clone();
Expand Down
2 changes: 1 addition & 1 deletion src/boolean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ mod test {
for val in [true, false].iter() {
let cs = ConstraintSystem::<Fr>::new_ref();
let a = Boolean::new_witness(cs.clone(), || Ok(*val))?;
let bytes = a.to_bytes()?;
let bytes = a.to_bytes_le()?;
assert_eq!(bytes.len(), 1);
let byte = &bytes[0];
assert_eq!(byte.value()?, *val as u8);
Expand Down
11 changes: 9 additions & 2 deletions src/boolean/not.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ use super::Boolean;

impl<F: Field> Boolean<F> {
fn _not(&self) -> Result<Self, SynthesisError> {
let mut result = self.clone();
result.not_in_place()?;
Ok(result)
}

pub fn not_in_place(&mut self) -> Result<(), SynthesisError> {
match *self {
Boolean::Constant(c) => Ok(Boolean::Constant(!c)),
Boolean::Var(ref v) => Ok(Boolean::Var(v.not().unwrap())),
Boolean::Constant(ref mut c) => *c = !*c,
Boolean::Var(ref mut v) => *v = v.not()?,
}
Ok(())
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/cmp.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use ark_ff::Field;
use ark_relations::r1cs::SynthesisError;

use crate::boolean::Boolean;
use crate::{boolean::Boolean, R1CSVar};

/// Specifies how to generate constraints for comparing two variables.
pub trait CmpGadget<F: Field> {
pub trait CmpGadget<F: Field>: R1CSVar<F> {
fn is_gt(&self, other: &Self) -> Result<Boolean<F>, SynthesisError> {
other.is_lt(self)
}
Expand Down
16 changes: 10 additions & 6 deletions src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,24 @@ pub trait ToBytesGadget<F: Field> {
/// Outputs a canonical, little-endian, byte decomposition of `self`.
///
/// This is the correct default for 99% of use cases.
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError>;
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError>;

/// Outputs a possibly non-unique byte decomposition of `self`.
///
/// If you're not absolutely certain that your usecase can get away with a
/// non-canonical representation, please use `self.to_bytes(cs)` instead.
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
self.to_bytes()
/// non-canonical representation, please use `self.to_bytes_le(cs)` instead.
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
self.to_bytes_le()
}
}

impl<'a, F: Field, T: 'a + ToBytesGadget<F>> ToBytesGadget<F> for &'a T {
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
(*self).to_bytes()
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
(*self).to_bytes_le()
}

fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
(*self).to_non_unique_bytes_le()
}
}

Expand Down
16 changes: 8 additions & 8 deletions src/fields/cubic_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,21 +435,21 @@ where
P: CubicExtVarConfig<BF>,
{
#[tracing::instrument(target = "r1cs")]
fn to_bytes(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
let mut c0 = self.c0.to_bytes()?;
let mut c1 = self.c1.to_bytes()?;
let mut c2 = self.c2.to_bytes()?;
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
let mut c0 = self.c0.to_bytes_le()?;
let mut c1 = self.c1.to_bytes_le()?;
let mut c2 = self.c2.to_bytes_le()?;
c0.append(&mut c1);
c0.append(&mut c2);

Ok(c0)
}

#[tracing::instrument(target = "r1cs")]
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
let mut c0 = self.c0.to_non_unique_bytes()?;
let mut c1 = self.c1.to_non_unique_bytes()?;
let mut c2 = self.c2.to_non_unique_bytes()?;
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
let mut c0 = self.c0.to_non_unique_bytes_le()?;
let mut c1 = self.c1.to_non_unique_bytes_le()?;
let mut c2 = self.c2.to_non_unique_bytes_le()?;

c0.append(&mut c1);
c0.append(&mut c2);
Expand Down
2 changes: 1 addition & 1 deletion src/fields/emulated_fp/allocated_field_var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ impl<TargetF: PrimeField, BaseF: PrimeField> ToBytesGadget<BaseF>
for AllocatedEmulatedFpVar<TargetF, BaseF>
{
#[tracing::instrument(target = "r1cs")]
fn to_bytes(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
fn to_bytes_le(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
let mut bits = self.to_bits_le()?;

let num_bits = TargetF::BigInt::NUM_LIMBS * 64;
Expand Down
8 changes: 4 additions & 4 deletions src/fields/emulated_fp/field_var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,23 +297,23 @@ impl<TargetF: PrimeField, BaseF: PrimeField> ToBytesGadget<BaseF>
/// Outputs the unique byte decomposition of `self` in *little-endian*
/// form.
#[tracing::instrument(target = "r1cs")]
fn to_bytes(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
fn to_bytes_le(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
match self {
Self::Constant(c) => Ok(UInt8::constant_vec(
c.into_bigint().to_bytes_le().as_slice(),
)),

Self::Var(v) => v.to_bytes(),
Self::Var(v) => v.to_bytes_le(),
}
}

#[tracing::instrument(target = "r1cs")]
fn to_non_unique_bytes(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
fn to_non_unique_bytes_le(&self) -> R1CSResult<Vec<UInt8<BaseF>>> {
match self {
Self::Constant(c) => Ok(UInt8::constant_vec(
c.into_bigint().to_bytes_le().as_slice(),
)),
Self::Var(v) => v.to_non_unique_bytes(),
Self::Var(v) => v.to_non_unique_bytes_le(),
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/fields/fp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ impl<F: PrimeField> ToBytesGadget<F> for AllocatedFp<F> {
/// This method enforces that the decomposition represents
/// an integer that is less than `F::MODULUS`.
#[tracing::instrument(target = "r1cs")]
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
let num_bits = F::BigInt::NUM_LIMBS * 64;
let mut bits = self.to_bits_le()?;
let remainder = core::iter::repeat(Boolean::constant(false)).take(num_bits - bits.len());
Expand All @@ -565,7 +565,7 @@ impl<F: PrimeField> ToBytesGadget<F> for AllocatedFp<F> {
}

#[tracing::instrument(target = "r1cs")]
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
let num_bits = F::BigInt::NUM_LIMBS * 64;
let mut bits = self.to_non_unique_bits_le()?;
let remainder = core::iter::repeat(Boolean::constant(false)).take(num_bits - bits.len());
Expand Down Expand Up @@ -957,22 +957,22 @@ impl<F: PrimeField> ToBytesGadget<F> for FpVar<F> {
/// Outputs the unique byte decomposition of `self` in *little-endian*
/// form.
#[tracing::instrument(target = "r1cs")]
fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
fn to_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
match self {
Self::Constant(c) => Ok(UInt8::constant_vec(
c.into_bigint().to_bytes_le().as_slice(),
)),
Self::Var(v) => v.to_bytes(),
Self::Var(v) => v.to_bytes_le(),
}
}

#[tracing::instrument(target = "r1cs")]
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
match self {
Self::Constant(c) => Ok(UInt8::constant_vec(
c.into_bigint().to_bytes_le().as_slice(),
)),
Self::Var(v) => v.to_non_unique_bytes(),
Self::Var(v) => v.to_non_unique_bytes_le(),
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/fields/quadratic_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,17 +435,17 @@ where
P: QuadExtVarConfig<BF>,
{
#[tracing::instrument(target = "r1cs")]
fn to_bytes(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
let mut c0 = self.c0.to_bytes()?;
let mut c1 = self.c1.to_bytes()?;
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
let mut c0 = self.c0.to_bytes_le()?;
let mut c1 = self.c1.to_bytes_le()?;
c0.append(&mut c1);
Ok(c0)
}

#[tracing::instrument(target = "r1cs")]
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
let mut c0 = self.c0.to_non_unique_bytes()?;
let mut c1 = self.c1.to_non_unique_bytes()?;
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::BasePrimeField>>, SynthesisError> {
let mut c0 = self.c0.to_non_unique_bytes_le()?;
let mut c1 = self.c1.to_non_unique_bytes_le()?;
c0.append(&mut c1);
Ok(c0)
}
Expand Down
28 changes: 14 additions & 14 deletions src/groups/curves/short_weierstrass/bls12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,20 @@ impl<P: Bls12Config> AllocVar<G1Prepared<P>, P::Fp> for G1PreparedVar<P> {
impl<P: Bls12Config> ToBytesGadget<P::Fp> for G1PreparedVar<P> {
#[inline]
#[tracing::instrument(target = "r1cs")]
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
let mut bytes = self.0.x.to_bytes()?;
let y_bytes = self.0.y.to_bytes()?;
let inf_bytes = self.0.infinity.to_bytes()?;
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
let mut bytes = self.0.x.to_bytes_le()?;
let y_bytes = self.0.y.to_bytes_le()?;
let inf_bytes = self.0.infinity.to_bytes_le()?;
bytes.extend_from_slice(&y_bytes);
bytes.extend_from_slice(&inf_bytes);
Ok(bytes)
}

#[tracing::instrument(target = "r1cs")]
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
let mut bytes = self.0.x.to_non_unique_bytes()?;
let y_bytes = self.0.y.to_non_unique_bytes()?;
let inf_bytes = self.0.infinity.to_non_unique_bytes()?;
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
let mut bytes = self.0.x.to_non_unique_bytes_le()?;
let y_bytes = self.0.y.to_non_unique_bytes_le()?;
let inf_bytes = self.0.infinity.to_non_unique_bytes_le()?;
bytes.extend_from_slice(&y_bytes);
bytes.extend_from_slice(&inf_bytes);
Ok(bytes)
Expand Down Expand Up @@ -174,21 +174,21 @@ impl<P: Bls12Config> AllocVar<G2Prepared<P>, P::Fp> for G2PreparedVar<P> {
impl<P: Bls12Config> ToBytesGadget<P::Fp> for G2PreparedVar<P> {
#[inline]
#[tracing::instrument(target = "r1cs")]
fn to_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
fn to_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
let mut bytes = Vec::new();
for coeffs in &self.ell_coeffs {
bytes.extend_from_slice(&coeffs.0.to_bytes()?);
bytes.extend_from_slice(&coeffs.1.to_bytes()?);
bytes.extend_from_slice(&coeffs.0.to_bytes_le()?);
bytes.extend_from_slice(&coeffs.1.to_bytes_le()?);
}
Ok(bytes)
}

#[tracing::instrument(target = "r1cs")]
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
fn to_non_unique_bytes_le(&self) -> Result<Vec<UInt8<P::Fp>>, SynthesisError> {
let mut bytes = Vec::new();
for coeffs in &self.ell_coeffs {
bytes.extend_from_slice(&coeffs.0.to_non_unique_bytes()?);
bytes.extend_from_slice(&coeffs.1.to_non_unique_bytes()?);
bytes.extend_from_slice(&coeffs.0.to_non_unique_bytes_le()?);
bytes.extend_from_slice(&coeffs.1.to_non_unique_bytes_le()?);
}
Ok(bytes)
}
Expand Down
Loading

0 comments on commit a124995

Please sign in to comment.