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 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 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 #[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 pub fn from_bytes_be(bytes: &[UInt8<F>]) -> Result<Self, SynthesisError> {
98 let bits = bytes
99 .iter()
100 .rev()
101 .flat_map(|b| b.to_bits_le().unwrap())
102 .collect::<Vec<_>>();
103 Ok(Self::from_bits_le(&bits))
104 }
105
106 pub fn from_bytes_le(bytes: &[UInt8<F>]) -> Result<Self, SynthesisError> {
128 let bits = bytes
129 .iter()
130 .flat_map(|b| b.to_bits_le().unwrap())
131 .collect::<Vec<_>>();
132 Ok(Self::from_bits_le(&bits))
133 }
134
135 pub fn to_bytes_be(&self) -> Result<Vec<UInt8<F>>, SynthesisError> {
136 let mut bytes = self.to_bytes_le()?;
137 bytes.reverse();
138 Ok(bytes)
139 }
140}
141
142impl<const N: usize, T: PrimUInt, F: Field> ToBitsGadget<F> for UInt<N, T, F> {
143 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
144 Ok(self.bits.to_vec())
145 }
146}
147
148impl<const N: usize, T: PrimUInt, F: Field> ToBitsGadget<F> for [UInt<N, T, F>] {
149 fn to_bits_le(&self) -> Result<Vec<Boolean<F>>, SynthesisError> {
152 let bits = self.iter().flat_map(|b| &b.bits).cloned().collect();
153 Ok(bits)
154 }
155}
156
157impl<const N: usize, T: PrimUInt, ConstraintF: Field> ToBytesGadget<ConstraintF>
162 for UInt<N, T, ConstraintF>
163{
164 #[tracing::instrument(target = "r1cs", skip(self))]
165 fn to_bytes_le(&self) -> Result<Vec<UInt8<ConstraintF>>, SynthesisError> {
166 Ok(self
167 .to_bits_le()?
168 .chunks(8)
169 .map(UInt8::from_bits_le)
170 .collect())
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177 use crate::{
178 prelude::EqGadget,
179 uint::test_utils::{run_unary_exhaustive, run_unary_random},
180 R1CSVar,
181 };
182 use ark_ff::PrimeField;
183 use ark_test_curves::bls12_381::Fr;
184
185 fn uint_to_bytes_le<T: PrimUInt, const N: usize, F: PrimeField>(
186 a: UInt<N, T, F>,
187 ) -> Result<(), SynthesisError> {
188 let cs = a.cs();
189 let computed = a.to_bytes_le()?;
190 let expected = UInt8::constant_vec(a.value()?.to_le_bytes().as_ref());
191 assert_eq!(expected.len(), computed.len());
192 assert_eq!(expected.value(), computed.value());
193 expected.enforce_equal(&computed)?;
194 if !a.is_constant() {
195 assert!(cs.is_satisfied().unwrap());
196 }
197 Ok(())
198 }
199
200 fn uint_to_bytes_be<T: PrimUInt, const N: usize, F: PrimeField>(
201 a: UInt<N, T, F>,
202 ) -> Result<(), SynthesisError> {
203 let cs = a.cs();
204 let computed = a.to_bytes_be()?;
205 let expected = UInt8::constant_vec(a.value()?.to_be_bytes().as_ref());
206 assert_eq!(expected.len(), computed.len());
207 assert_eq!(expected.value(), computed.value());
208 expected.enforce_equal(&computed)?;
209 if !a.is_constant() {
210 assert!(cs.is_satisfied().unwrap());
211 }
212 Ok(())
213 }
214
215 fn uint_from_bytes_le<T: PrimUInt, const N: usize, F: PrimeField>(
216 expected: UInt<N, T, F>,
217 ) -> Result<(), SynthesisError> {
218 let cs = expected.cs();
219 let mode = if expected.is_constant() {
220 AllocationMode::Constant
221 } else {
222 AllocationMode::Witness
223 };
224 let computed = {
225 let value = expected.value()?.to_le_bytes();
226 let a = Vec::<UInt8<F>>::new_variable(cs.clone(), || Ok(value.as_ref()), mode)?;
227 UInt::from_bytes_le(&a)?
228 };
229 assert_eq!(expected.value(), computed.value());
230 expected.enforce_equal(&computed)?;
231 if !expected.is_constant() {
232 assert!(cs.is_satisfied().unwrap());
233 }
234 Ok(())
235 }
236
237 fn uint_from_bytes_be<T: PrimUInt, const N: usize, F: PrimeField>(
238 expected: UInt<N, T, F>,
239 ) -> Result<(), SynthesisError> {
240 let cs = expected.cs();
241 let mode = if expected.is_constant() {
242 AllocationMode::Constant
243 } else {
244 AllocationMode::Witness
245 };
246 let computed = {
247 let value = expected.value()?.to_be_bytes();
248 let a = Vec::<UInt8<F>>::new_variable(cs.clone(), || Ok(value.as_ref()), mode)?;
249 UInt::from_bytes_be(&a)?
250 };
251 assert_eq!(expected.value(), computed.value());
252 expected.enforce_equal(&computed)?;
253 if !expected.is_constant() {
254 assert!(cs.is_satisfied().unwrap());
255 }
256 Ok(())
257 }
258
259 #[test]
260 fn u8_to_bytes_le() {
261 run_unary_exhaustive(uint_to_bytes_le::<u8, 8, Fr>).unwrap()
262 }
263
264 #[test]
265 fn u16_to_bytes_le() {
266 run_unary_random::<1000, 16, _, _>(uint_to_bytes_le::<u16, 16, Fr>).unwrap()
267 }
268
269 #[test]
270 fn u32_to_bytes_le() {
271 run_unary_random::<1000, 32, _, _>(uint_to_bytes_le::<u32, 32, Fr>).unwrap()
272 }
273
274 #[test]
275 fn u64_to_bytes_le() {
276 run_unary_random::<1000, 64, _, _>(uint_to_bytes_le::<u64, 64, Fr>).unwrap()
277 }
278
279 #[test]
280 fn u128_to_bytes_le() {
281 run_unary_random::<1000, 128, _, _>(uint_to_bytes_le::<u128, 128, Fr>).unwrap()
282 }
283
284 #[test]
285 fn u8_to_bytes_be() {
286 run_unary_exhaustive(uint_to_bytes_be::<u8, 8, Fr>).unwrap()
287 }
288
289 #[test]
290 fn u16_to_bytes_be() {
291 run_unary_random::<1000, 16, _, _>(uint_to_bytes_be::<u16, 16, Fr>).unwrap()
292 }
293
294 #[test]
295 fn u32_to_bytes_be() {
296 run_unary_random::<1000, 32, _, _>(uint_to_bytes_be::<u32, 32, Fr>).unwrap()
297 }
298
299 #[test]
300 fn u64_to_bytes_be() {
301 run_unary_random::<1000, 64, _, _>(uint_to_bytes_be::<u64, 64, Fr>).unwrap()
302 }
303
304 #[test]
305 fn u128_to_bytes_be() {
306 run_unary_random::<1000, 128, _, _>(uint_to_bytes_be::<u128, 128, Fr>).unwrap()
307 }
308
309 #[test]
310 fn u8_from_bytes_le() {
311 run_unary_exhaustive(uint_from_bytes_le::<u8, 8, Fr>).unwrap()
312 }
313
314 #[test]
315 fn u16_from_bytes_le() {
316 run_unary_random::<1000, 16, _, _>(uint_from_bytes_le::<u16, 16, Fr>).unwrap()
317 }
318
319 #[test]
320 fn u32_from_bytes_le() {
321 run_unary_random::<1000, 32, _, _>(uint_from_bytes_le::<u32, 32, Fr>).unwrap()
322 }
323
324 #[test]
325 fn u64_from_bytes_le() {
326 run_unary_random::<1000, 64, _, _>(uint_from_bytes_le::<u64, 64, Fr>).unwrap()
327 }
328
329 #[test]
330 fn u128_from_bytes_le() {
331 run_unary_random::<1000, 128, _, _>(uint_from_bytes_le::<u128, 128, Fr>).unwrap()
332 }
333
334 #[test]
335 fn u8_from_bytes_be() {
336 run_unary_exhaustive(uint_from_bytes_be::<u8, 8, Fr>).unwrap()
337 }
338
339 #[test]
340 fn u16_from_bytes_be() {
341 run_unary_random::<1000, 16, _, _>(uint_from_bytes_be::<u16, 16, Fr>).unwrap()
342 }
343
344 #[test]
345 fn u32_from_bytes_be() {
346 run_unary_random::<1000, 32, _, _>(uint_from_bytes_be::<u32, 32, Fr>).unwrap()
347 }
348
349 #[test]
350 fn u64_from_bytes_be() {
351 run_unary_random::<1000, 64, _, _>(uint_from_bytes_be::<u64, 64, Fr>).unwrap()
352 }
353
354 #[test]
355 fn u128_from_bytes_be() {
356 run_unary_random::<1000, 128, _, _>(uint_from_bytes_be::<u128, 128, Fr>).unwrap()
357 }
358}