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}