arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/src/bits/mod.rs
src/bits/mod.rsRaw
  1use crate::{
  2    bits::{boolean::Boolean, uint8::UInt8},
  3    Vec,
  4};
  5use ark_ff::Field;
  6use ark_relations::r1cs::SynthesisError;
  7
  8/// This module contains `Boolean`, a R1CS equivalent of the `bool` type.
  9pub mod boolean;
 10/// This module contains `UInt8`, a R1CS equivalent of the `u8` type.
 11pub mod uint8;
 12/// This module contains a macro for generating `UIntN` types, which are R1CS
 13/// equivalents of `N`-bit unsigned integers.
 14#[macro_use]
 15pub mod uint;
 16
 17make_uint!(UInt16, 16, u16, uint16, "`U16`", "`u16`", "16");
 18make_uint!(UInt32, 32, u32, uint32, "`U32`", "`u32`", "32");
 19make_uint!(UInt64, 64, u64, uint64, "`U64`", "`u64`", "64");
 20make_uint!(UInt128, 128, u128, uint128, "`U128`", "`u128`", "128");
 21
 22/// Specifies constraints for conversion to a little-endian bit representation
 23/// of `self`.
 24pub trait ToBitsGadget<F: Field> {
 25    /// Outputs the canonical little-endian bit-wise representation of `self`.
 26    ///
 27    /// This is the correct default for 99% of use cases.
 28    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError>;
 29
 30    /// Outputs a possibly non-unique little-endian bit-wise representation of
 31    /// `self`.
 32    ///
 33    /// If you're not absolutely certain that your usecase can get away with a
 34    /// non-canonical representation, please use `self.to_bits()` instead.
 35    fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 36        self.to_bits_le()
 37    }
 38
 39    /// Outputs the canonical big-endian bit-wise representation of `self`.
 40    fn to_bits_be(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 41        let mut res = self.to_bits_le()?;
 42        res.reverse();
 43        Ok(res)
 44    }
 45
 46    /// Outputs a possibly non-unique big-endian bit-wise representation of
 47    /// `self`.
 48    fn to_non_unique_bits_be(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 49        let mut res = self.to_non_unique_bits_le()?;
 50        res.reverse();
 51        Ok(res)
 52    }
 53}
 54
 55impl<F: Field> ToBitsGadget<F> for Boolean<F> {
 56    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 57        Ok(vec![self.clone()])
 58    }
 59}
 60
 61impl<F: Field> ToBitsGadget<F> for [Boolean<F>] {
 62    /// Outputs `self`.
 63    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 64        Ok(self.to_vec())
 65    }
 66}
 67
 68impl<F: Field> ToBitsGadget<F> for UInt8<F> {
 69    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 70        Ok(self.bits.to_vec())
 71    }
 72}
 73
 74impl<F: Field> ToBitsGadget<F> for [UInt8<F>] {
 75    /// Interprets `self` as an integer, and outputs the little-endian
 76    /// bit-wise decomposition of that integer.
 77    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 78        let bits = self.iter().flat_map(|b| &b.bits).cloned().collect();
 79        Ok(bits)
 80    }
 81}
 82
 83impl<F: Field, T> ToBitsGadget<F> for Vec<T>
 84where
 85    [T]: ToBitsGadget<F>,
 86{
 87    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 88        self.as_slice().to_bits_le().map(|v| v.to_vec())
 89    }
 90
 91    fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 92        self.as_slice().to_non_unique_bits_le().map(|v| v.to_vec())
 93    }
 94}
 95
 96/// Specifies constraints for conversion to a little-endian byte representation
 97/// of `self`.
 98pub trait ToBytesGadget<F: Field> {
 99    /// Outputs a canonical, little-endian, byte decomposition of `self`.
100    ///
101    /// This is the correct default for 99% of use cases.
102    fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError>;
103
104    /// Outputs a possibly non-unique byte decomposition of `self`.
105    ///
106    /// If you're not absolutely certain that your usecase can get away with a
107    /// non-canonical representation, please use `self.to_bytes(cs)` instead.
108    fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
109        self.to_bytes()
110    }
111}
112
113impl<F: Field> ToBytesGadget<F> for [UInt8<F>] {
114    fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
115        Ok(self.to_vec())
116    }
117}
118
119impl<F: Field> ToBytesGadget<F> for Vec<UInt8<F>> {
120    fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
121        Ok(self.clone())
122    }
123}
124
125impl<'a, F: Field, T: 'a + ToBytesGadget<F>> ToBytesGadget<F> for &'a T {
126    fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
127        (*self).to_bytes()
128    }
129}
130
131impl<'a, F: Field> ToBytesGadget<F> for &'a [UInt8<F>] {
132    fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
133        Ok(self.to_vec())
134    }
135}