arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/src/uint/convert.rs
src/uint/convert.rsRaw
  1use crate::convert::*;
  2use crate::fields::fp::FpVar;
  3
  4use super::*;
  5
  6impl<const N: usize, F: Field, T: PrimUInt> UInt<N, T, F> {
  7    /// Converts `self` into a field element. The elements comprising `self` are
  8    /// interpreted as a little-endian bit order representation of a field element.
  9    ///
 10    /// # Panics
 11    /// Assumes that `N` is equal to at most the number of bits in `F::MODULUS_BIT_SIZE - 1`, and panics otherwise.
 12    pub fn to_fp(&self) -> Result<FpVar<F>, SynthesisError>
 13    where
 14        F: PrimeField,
 15    {
 16        assert!(N <= F::MODULUS_BIT_SIZE as usize - 1);
 17
 18        Boolean::le_bits_to_fp(&self.bits)
 19    }
 20
 21    /// Converts a field element into its little-endian bit order representation.
 22    ///
 23    /// # Panics
 24    ///
 25    /// Assumes that `N` is at most the number of bits in `F::MODULUS_BIT_SIZE - 1`, and panics otherwise.
 26    pub fn from_fp(other: &FpVar<F>) -> Result<(Self, FpVar<F>), SynthesisError>
 27    where
 28        F: PrimeField,
 29    {
 30        let (bits, rest) = other.to_bits_le_with_top_bits_zero(N)?;
 31        let result = Self::from_bits_le(&bits);
 32        Ok((result, rest))
 33    }
 34
 35    /// Converts a little-endian byte order representation of bits into a
 36    /// `UInt`.
 37    ///
 38    /// ```
 39    /// # fn main() -> Result<(), ark_relations::r1cs::SynthesisError> {
 40    /// // We'll use the BLS12-381 scalar field for our constraints.
 41    /// use ark_test_curves::bls12_381::Fr;
 42    /// use ark_relations::r1cs::*;
 43    /// use ark_r1cs_std::prelude::*;
 44    ///
 45    /// let cs = ConstraintSystem::<Fr>::new_ref();
 46    /// let var = UInt8::new_witness(cs.clone(), || Ok(128))?;
 47    ///
 48    /// let f = Boolean::FALSE;
 49    /// let t = Boolean::TRUE;
 50    ///
 51    /// // Construct [0, 0, 0, 0, 0, 0, 0, 1]
 52    /// let mut bits = vec![f.clone(); 7];
 53    /// bits.push(t);
 54    ///
 55    /// let mut c = UInt8::from_bits_le(&bits);
 56    /// var.enforce_equal(&c)?;
 57    /// assert!(cs.is_satisfied().unwrap());
 58    /// # Ok(())
 59    /// # }
 60    /// ```
 61    #[tracing::instrument(target = "r1cs")]
 62    pub fn from_bits_le(bits: &[Boolean<F>]) -> Self {
 63        assert_eq!(bits.len(), N);
 64        let bits = <&[Boolean<F>; N]>::try_from(bits).unwrap().clone();
 65        let value_exists = bits.iter().all(|b| b.value().is_ok());
 66        let mut value = T::zero();
 67        for (i, b) in bits.iter().enumerate() {
 68            if let Ok(b) = b.value() {
 69                value = value + (T::from(b as u8).unwrap() << i);
 70            }
 71        }
 72        let value = value_exists.then_some(value);
 73        Self { bits, value }
 74    }
 75}
 76
 77impl<const N: usize, T: PrimUInt, F: Field> ToBitsGadget<F> for UInt<N, T, F> {
 78    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 79        Ok(self.bits.to_vec())
 80    }
 81}
 82
 83impl<const N: usize, T: PrimUInt, F: Field> ToBitsGadget<F> for [UInt<N, T, F>] {
 84    /// Interprets `self` as an integer, and outputs the little-endian
 85    /// bit-wise decomposition of that integer.
 86    fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
 87        let bits = self.iter().flat_map(|b| &b.bits).cloned().collect();
 88        Ok(bits)
 89    }
 90}
 91
 92/*****************************************************************************************/
 93/********************************* Conversions to bytes. *********************************/
 94/*****************************************************************************************/
 95
 96impl<const N: usize, T: PrimUInt, ConstraintF: Field> ToBytesGadget<ConstraintF>
 97    for UInt<N, T, ConstraintF>
 98{
 99    #[tracing::instrument(target = "r1cs", skip(self))]
100    fn to_bytes(&self) -> Result<Vec<UInt8<ConstraintF>>, SynthesisError> {
101        Ok(self
102            .to_bits_le()?
103            .chunks(8)
104            .map(UInt8::from_bits_le)
105            .collect())
106    }
107}
108
109impl<const N: usize, T: PrimUInt, F: Field> ToBytesGadget<F> for [UInt<N, T, F>] {
110    fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
111        let mut bytes = Vec::with_capacity(self.len() * (N / 8));
112        for elem in self {
113            bytes.extend_from_slice(&elem.to_bytes()?);
114        }
115        Ok(bytes)
116    }
117}
118
119impl<const N: usize, T: PrimUInt, F: Field> ToBytesGadget<F> for Vec<UInt<N, T, F>> {
120    fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
121        self.as_slice().to_bytes()
122    }
123}
124
125impl<'a, const N: usize, T: PrimUInt, F: Field> ToBytesGadget<F> for &'a [UInt<N, T, F>] {
126    fn to_bytes(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
127        (*self).to_bytes()
128    }
129}